@profullstack/hqtui-demo 0.1.1 → 0.1.3

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.
Files changed (44) hide show
  1. package/README.md +51 -8
  2. package/dist/main.js +34 -11
  3. package/dist/main.js.map +1 -1
  4. package/dist/screens/index.js +4 -0
  5. package/dist/screens/index.js.map +1 -1
  6. package/dist/screens/network.js +86 -0
  7. package/dist/screens/network.js.map +1 -0
  8. package/dist/screens/services.js +121 -0
  9. package/dist/screens/services.js.map +1 -0
  10. package/dist/screens/sessions.js +80 -0
  11. package/dist/screens/sessions.js.map +1 -0
  12. package/dist/screens/traffic.js +183 -0
  13. package/dist/screens/traffic.js.map +1 -0
  14. package/dist/simulation.js +6 -0
  15. package/dist/simulation.js.map +1 -1
  16. package/dist/state.js +4 -1
  17. package/dist/state.js.map +1 -1
  18. package/dist/system/common.js +2 -0
  19. package/dist/system/common.js.map +1 -1
  20. package/dist/system/linux-telemetry.js +420 -0
  21. package/dist/system/linux-telemetry.js.map +1 -0
  22. package/dist/system/linux-traffic.js +282 -0
  23. package/dist/system/linux-traffic.js.map +1 -0
  24. package/dist/system/linux.js +90 -26
  25. package/dist/system/linux.js.map +1 -1
  26. package/dist/system/simulated-telemetry.js +267 -0
  27. package/dist/system/simulated-telemetry.js.map +1 -0
  28. package/dist/system/telemetry.js +44 -0
  29. package/dist/system/telemetry.js.map +1 -0
  30. package/package.json +4 -3
  31. package/src/main.ts +26 -11
  32. package/src/screens/index.ts +4 -0
  33. package/src/screens/network.ts +91 -0
  34. package/src/screens/services.ts +136 -0
  35. package/src/screens/sessions.ts +85 -0
  36. package/src/screens/traffic.ts +199 -0
  37. package/src/simulation.ts +12 -0
  38. package/src/state.ts +7 -2
  39. package/src/system/common.ts +2 -0
  40. package/src/system/linux-telemetry.ts +431 -0
  41. package/src/system/linux-traffic.ts +375 -0
  42. package/src/system/linux.ts +95 -21
  43. package/src/system/simulated-telemetry.ts +280 -0
  44. package/src/system/telemetry.ts +263 -0
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Simulated telemetry so `--sim` populates every screen, and so CI snapshots
3
+ * of the traffic and session views are deterministic.
4
+ */
5
+ const USERS = ["anthony", "deploy", "ci", "root", "postgres"];
6
+ const HOSTS = ["10.0.4.17", "203.0.113.42", "198.51.100.9", "192.168.1.42", "172.16.0.8"];
7
+ const PATHS = ["/", "/api/health", "/api/users", "/assets/app.js", "/docs", "/api/ws", "/login", "/api/metrics"];
8
+ const AGENTS = ["nginx", "sshd", "systemd", "cron", "kernel", "dockerd"];
9
+ const UNITS = [
10
+ ["nginx", "active", "running", "A high performance web server"],
11
+ ["postgresql", "active", "running", "PostgreSQL RDBMS"],
12
+ ["redis-server", "active", "running", "Advanced key-value store"],
13
+ ["ssh", "active", "running", "OpenBSD Secure Shell server"],
14
+ ["cron", "active", "running", "Regular background program processing"],
15
+ ["docker", "active", "running", "Docker Application Container Engine"],
16
+ ["systemd-resolved", "active", "running", "Network Name Resolution"],
17
+ ["backup", "failed", "failed", "Nightly backup job"],
18
+ ["telemetry-agent", "inactive", "dead", "Vendor telemetry collector"],
19
+ ];
20
+ const PROTOCOLS = ["HTTPS", "HTTP", "SSH", "Postgres", "Redis", "DNS", "SMTP", "ephemeral"];
21
+ function push(history, value, limit = 240) {
22
+ history.push(value);
23
+ if (history.length > limit)
24
+ history.shift();
25
+ }
26
+ function clock(offsetSeconds = 0) {
27
+ return new Date(Date.now() - offsetSeconds * 1000).toTimeString().slice(0, 8);
28
+ }
29
+ /** Fill in every telemetry section with plausible, drifting values. */
30
+ export function updateTelemetry(t, random, tick, cpu) {
31
+ // --- sessions -------------------------------------------------------------
32
+ if (t.sessions.length === 0) {
33
+ t.sessions = [
34
+ { user: "anthony", tty: "pts/0", from: "10.0.4.17", loginAt: "09:14", idle: ".", what: "bun run dev" },
35
+ { user: "deploy", tty: "pts/1", from: "203.0.113.42", loginAt: "11:02", idle: "00:04", what: "tail -f app.log" },
36
+ { user: "anthony", tty: "pts/2", from: "10.0.4.17", loginAt: "11:40", idle: "00:12", what: "psql" },
37
+ ];
38
+ t.logins = Array.from({ length: 18 }, (_, i) => ({
39
+ user: USERS[i % USERS.length],
40
+ tty: `pts/${i % 4}`,
41
+ from: HOSTS[i % HOSTS.length],
42
+ when: `Aug ${20 + (i % 9)} ${String(7 + (i % 12)).padStart(2, "0")}:${String((i * 7) % 60).padStart(2, "0")}`,
43
+ status: i < 3 ? "still" : "ok",
44
+ }));
45
+ t.failedLogins = Array.from({ length: 6 }, (_, i) => ({
46
+ user: ["root", "admin", "test", "oracle", "ubuntu", "git"][i],
47
+ tty: "ssh",
48
+ from: `185.${100 + i}.${20 + i * 3}.${9 + i}`,
49
+ when: `Aug 30 0${i}:${String((i * 11) % 60).padStart(2, "0")}`,
50
+ status: "failed",
51
+ }));
52
+ }
53
+ push(t.sessionHistory, t.sessions.length + (random() < 0.1 ? 1 : 0));
54
+ // --- sockets and protocols ------------------------------------------------
55
+ const connectionCount = Math.round(40 + cpu * 60 + random() * 15);
56
+ t.protocols = PROTOCOLS.map((protocol, i) => {
57
+ const weight = [0.42, 0.12, 0.06, 0.1, 0.07, 0.08, 0.03, 0.12][i];
58
+ const total = Math.max(0, Math.round(connectionCount * weight * (0.7 + random() * 0.6)));
59
+ const inbound = protocol === "HTTPS" || protocol === "HTTP" || protocol === "SSH"
60
+ ? Math.round(total * 0.75)
61
+ : Math.round(total * 0.15);
62
+ return { protocol, inbound, outbound: total - inbound, total };
63
+ }).sort((a, b) => b.total - a.total);
64
+ t.inboundConnections = t.protocols.reduce((a, p) => a + p.inbound, 0);
65
+ t.outboundConnections = t.protocols.reduce((a, p) => a + p.outbound, 0);
66
+ push(t.connectionHistory, t.inboundConnections + t.outboundConnections);
67
+ t.remotes = HOSTS.map((host, i) => ({
68
+ host,
69
+ connections: Math.max(1, Math.round((8 - i) * (0.6 + random()))),
70
+ protocols: [PROTOCOLS[i % PROTOCOLS.length], PROTOCOLS[(i + 3) % PROTOCOLS.length]].join(", "),
71
+ })).sort((a, b) => b.connections - a.connections);
72
+ t.connections = t.remotes.slice(0, 12).map((remote, i) => ({
73
+ proto: i % 5 === 0 ? "udp" : "tcp",
74
+ local: `10.0.0.7:${40000 + i * 13}`,
75
+ remote: `${remote.host}:${[443, 443, 22, 5432, 6379][i % 5]}`,
76
+ state: "ESTAB",
77
+ process: ["bun/1261", "node/8437", "sshd/1024", "postgres/2217", "redis/1555"][i % 5],
78
+ }));
79
+ t.listeners = [
80
+ { proto: "tcp", address: "0.0.0.0", port: "443", process: "nginx/981" },
81
+ { proto: "tcp", address: "0.0.0.0", port: "80", process: "nginx/981" },
82
+ { proto: "tcp", address: "0.0.0.0", port: "22", process: "sshd/1024" },
83
+ { proto: "tcp", address: "127.0.0.1", port: "5432", process: "postgres/2217" },
84
+ { proto: "tcp", address: "127.0.0.1", port: "6379", process: "redis/1555" },
85
+ { proto: "tcp", address: "0.0.0.0", port: "3000", process: "bun/1261" },
86
+ { proto: "udp", address: "0.0.0.0", port: "53", process: "resolved/712" },
87
+ ];
88
+ // --- kernel network counters ---------------------------------------------
89
+ const inSegs = 4000 + cpu * 12000 + random() * 2500;
90
+ const outSegs = 3500 + cpu * 11000 + random() * 2200;
91
+ const retrans = Math.max(0, outSegs * (0.001 + random() * 0.004));
92
+ t.net.tcpInSegs += inSegs;
93
+ t.net.tcpOutSegs += outSegs;
94
+ t.net.tcpRetransSegs += retrans;
95
+ t.net.tcpEstablished = t.inboundConnections + t.outboundConnections;
96
+ t.net.tcpPassiveOpens += Math.round(random() * 12);
97
+ t.net.tcpActiveOpens += Math.round(random() * 8);
98
+ t.net.tcpOutRsts += Math.round(random() * 3);
99
+ t.net.udpInDatagrams += Math.round(200 + random() * 400);
100
+ t.net.udpOutDatagrams += Math.round(180 + random() * 350);
101
+ t.net.icmpInMsgs += Math.round(random() * 2);
102
+ t.net.icmpOutMsgs += Math.round(random() * 2);
103
+ t.net.rates = {
104
+ inSegs,
105
+ outSegs,
106
+ retrans,
107
+ passiveOpens: random() * 12,
108
+ activeOpens: random() * 8,
109
+ udpIn: 200 + random() * 400,
110
+ udpOut: 180 + random() * 350,
111
+ };
112
+ t.net.retransRatio = retrans / Math.max(1, outSegs);
113
+ push(t.netInHistory, inSegs);
114
+ push(t.netOutHistory, outSegs);
115
+ push(t.retransHistory, retrans);
116
+ // --- ssh ------------------------------------------------------------------
117
+ if (t.ssh.length === 0 || (tick % 40 === 0 && random() < 0.7)) {
118
+ const failed = random() < 0.45;
119
+ t.ssh.push({
120
+ time: clock(),
121
+ action: failed ? (random() < 0.5 ? "failed" : "invalid") : "accepted",
122
+ user: failed ? ["root", "admin", "test", "oracle"][Math.floor(random() * 4)] : USERS[Math.floor(random() * 3)],
123
+ from: failed ? `185.${Math.floor(random() * 255)}.${Math.floor(random() * 255)}.${Math.floor(random() * 255)}` : HOSTS[Math.floor(random() * 3)],
124
+ method: failed ? "password" : "publickey",
125
+ });
126
+ if (t.ssh.length > 40)
127
+ t.ssh.shift();
128
+ }
129
+ // --- http -----------------------------------------------------------------
130
+ const requestsPerSecond = 18 + cpu * 90 + random() * 25;
131
+ if (!t.http) {
132
+ t.http = {
133
+ source: "/var/log/nginx/access.log",
134
+ requestsPerSecond,
135
+ total: 0,
136
+ statusClasses: [],
137
+ topPaths: [],
138
+ topClients: [],
139
+ methods: [],
140
+ upgrades: 0,
141
+ recent: [],
142
+ history: [],
143
+ };
144
+ }
145
+ const http = t.http;
146
+ http.requestsPerSecond = requestsPerSecond;
147
+ http.total += Math.round(requestsPerSecond);
148
+ push(http.history, requestsPerSecond);
149
+ http.upgrades += random() < 0.15 ? 1 : 0;
150
+ http.statusClasses = [
151
+ { class: "2xx", count: Math.round(http.total * 0.86) },
152
+ { class: "3xx", count: Math.round(http.total * 0.06) },
153
+ { class: "4xx", count: Math.round(http.total * 0.06) },
154
+ { class: "5xx", count: Math.round(http.total * 0.015) },
155
+ { class: "1xx", count: http.upgrades },
156
+ ];
157
+ http.topPaths = PATHS.map((path, i) => ({
158
+ path,
159
+ count: Math.round(http.total * [0.3, 0.18, 0.14, 0.12, 0.09, 0.07, 0.06, 0.04][i]),
160
+ }));
161
+ http.topClients = HOSTS.map((client, i) => ({ client, count: Math.round(http.total * (0.3 - i * 0.05)) }));
162
+ http.methods = [
163
+ { method: "GET", count: Math.round(http.total * 0.78) },
164
+ { method: "POST", count: Math.round(http.total * 0.16) },
165
+ { method: "PUT", count: Math.round(http.total * 0.04) },
166
+ { method: "DELETE", count: Math.round(http.total * 0.02) },
167
+ ];
168
+ if (tick % 3 === 0) {
169
+ const roll = random();
170
+ http.recent.unshift({
171
+ time: clock(),
172
+ method: roll < 0.8 ? "GET" : roll < 0.95 ? "POST" : "DELETE",
173
+ path: PATHS[Math.floor(random() * PATHS.length)],
174
+ status: roll < 0.86 ? "200" : roll < 0.92 ? "304" : roll < 0.98 ? "404" : "500",
175
+ client: HOSTS[Math.floor(random() * HOSTS.length)],
176
+ bytes: Math.round(200 + random() * 24000),
177
+ });
178
+ if (http.recent.length > 40)
179
+ http.recent.pop();
180
+ }
181
+ // --- services, containers, filesystems ------------------------------------
182
+ if (t.services.length === 0) {
183
+ t.services = UNITS.map(([name, active, sub, description]) => ({ name, active, sub, description }));
184
+ t.containers = [
185
+ { id: "9f2c1a4b7e33", name: "api", image: "hqtui/api:1.4.2", status: "Up 2 hours", cpu: "12.4%", memory: "184 MiB" },
186
+ { id: "3ab7f0912cd5", name: "worker", image: "hqtui/worker:1.4.2", status: "Up 2 hours", cpu: "6.1%", memory: "96 MiB" },
187
+ { id: "77e10cc4a9b2", name: "postgres", image: "postgres:16", status: "Up 5 days", cpu: "3.8%", memory: "412 MiB" },
188
+ { id: "1cd8e5b60f47", name: "redis", image: "redis:7-alpine", status: "Up 5 days", cpu: "0.7%", memory: "34 MiB" },
189
+ ];
190
+ t.filesystems = [
191
+ { mount: "/", device: "/dev/nvme0n1p2", type: "ext4", size: 512 * 1024 ** 3, used: 136 * 1024 ** 3, inodesUsed: 1_240_000, inodesTotal: 32_000_000 },
192
+ { mount: "/home", device: "/dev/nvme0n1p3", type: "ext4", size: 980 * 1024 ** 3, used: 622 * 1024 ** 3, inodesUsed: 4_100_000, inodesTotal: 61_000_000 },
193
+ { mount: "/data", device: "/dev/sda1", type: "xfs", size: 2 * 1024 ** 4, used: 1.02 * 1024 ** 4, inodesUsed: 812_000, inodesTotal: 210_000_000 },
194
+ { mount: "/boot", device: "/dev/nvme0n1p1", type: "vfat", size: 512 * 1024 ** 2, used: 148 * 1024 ** 2, inodesUsed: 0, inodesTotal: 0 },
195
+ ];
196
+ t.gpus = [{
197
+ name: "NVIDIA RTX A2000", utilization: 0.34, memoryUsed: 2.1 * 1024 ** 3,
198
+ memoryTotal: 6 * 1024 ** 3, temperature: 52, power: 34.5,
199
+ }];
200
+ t.power = { battery: 96, charging: false, timeRemaining: "Full", powerDraw: 14.2, acConnected: true };
201
+ }
202
+ t.gpus[0].utilization = Math.max(0.02, Math.min(1, cpu * 0.8 + random() * 0.2));
203
+ t.gpus[0].temperature = 44 + t.gpus[0].utilization * 26;
204
+ if (t.power)
205
+ t.power.powerDraw = 8 + cpu * 22;
206
+ // --- kernel counters ------------------------------------------------------
207
+ t.kernel.contextSwitchRate = 3000 + cpu * 18000 + random() * 1500;
208
+ t.kernel.interruptRate = 2000 + cpu * 9000 + random() * 900;
209
+ t.kernel.forkRate = 4 + cpu * 60 + random() * 8;
210
+ t.kernel.contextSwitches += t.kernel.contextSwitchRate / 10;
211
+ t.kernel.interrupts += t.kernel.interruptRate / 10;
212
+ t.kernel.forks += t.kernel.forkRate / 10;
213
+ t.kernel.procsRunning = Math.max(1, Math.round(cpu * 14));
214
+ t.kernel.procsBlocked = random() < 0.15 ? 1 : 0;
215
+ t.kernel.entropy = Math.round(3000 + random() * 800);
216
+ t.kernel.openFiles = Math.round(2000 + cpu * 3000);
217
+ t.kernel.maxFiles = 9_223_372;
218
+ t.kernel.pageIn += Math.round(random() * 400);
219
+ t.kernel.pageOut += Math.round(random() * 300);
220
+ t.states = {
221
+ running: t.kernel.procsRunning,
222
+ sleeping: 240 + Math.round(random() * 20),
223
+ stopped: 0,
224
+ zombie: random() < 0.08 ? 1 : 0,
225
+ total: 0,
226
+ };
227
+ t.states.total = t.states.running + t.states.sleeping + t.states.stopped + t.states.zombie;
228
+ // --- interfaces -----------------------------------------------------------
229
+ if (t.interfaces.length === 0) {
230
+ t.interfaces = [
231
+ { name: "eth0", ip: "10.0.0.7", mac: "ac:de:48:00:11:22", state: "up", mtu: 1500, rxRate: 0, txRate: 0, rxTotal: 0, txTotal: 0, rxHistory: [], txHistory: [], errors: 0, drops: 0 },
232
+ { name: "wg0", ip: "100.84.2.19", mac: "00:00:00:00:00:00", state: "up", mtu: 1280, rxRate: 0, txRate: 0, rxTotal: 0, txTotal: 0, rxHistory: [], txHistory: [], errors: 0, drops: 0 },
233
+ ];
234
+ }
235
+ t.interfaces.forEach((iface, i) => {
236
+ const scale = i === 0 ? 1 : 0.25;
237
+ iface.rxRate = Math.max(0, (6e6 + Math.sin(tick / 30 + i) * 3e6 + random() * 4e6) * scale);
238
+ iface.txRate = Math.max(0, (1.8e6 + Math.sin(tick / 20 + i) * 1e6 + random() * 1.5e6) * scale);
239
+ iface.rxTotal += iface.rxRate / 10;
240
+ iface.txTotal += iface.txRate / 10;
241
+ push(iface.rxHistory, iface.rxRate);
242
+ push(iface.txHistory, iface.txRate);
243
+ });
244
+ // --- journal --------------------------------------------------------------
245
+ if (tick % 8 === 0) {
246
+ const level = random() < 0.06 ? "ERROR" : random() < 0.16 ? "WARN" : random() < 0.3 ? "DEBUG" : "INFO";
247
+ const unit = AGENTS[Math.floor(random() * AGENTS.length)];
248
+ const messages = {
249
+ nginx: ["client closed connection while waiting for request", `${Math.round(random() * 400)} requests served`, "upstream timed out"],
250
+ sshd: ["Accepted publickey for anthony", "Connection closed by authenticating user root", "Received disconnect"],
251
+ systemd: ["Started Daily apt download activities", "Reloading nginx configuration", "Reached target Timers"],
252
+ cron: ["(anthony) CMD (run-parts /etc/cron.hourly)", "pam_unix(cron:session): session opened"],
253
+ kernel: ["TCP: request_sock_TCP: Possible SYN flooding", "EXT4-fs: mounted filesystem with ordered data mode"],
254
+ dockerd: ["container start", "health check passed", "image pull complete"],
255
+ };
256
+ const pool = messages[unit] ?? ["event"];
257
+ t.journal.push({
258
+ time: clock(),
259
+ level,
260
+ unit,
261
+ message: pool[Math.floor(random() * pool.length)],
262
+ });
263
+ if (t.journal.length > 200)
264
+ t.journal.shift();
265
+ }
266
+ }
267
+ //# sourceMappingURL=simulated-telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulated-telemetry.js","sourceRoot":"","sources":["../../src/system/simulated-telemetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /** Everything the demo can observe beyond classic CPU/memory/disk monitoring. */
2
+ export function emptyTelemetry() {
3
+ return {
4
+ sessions: [],
5
+ logins: [],
6
+ failedLogins: [],
7
+ connections: [],
8
+ listeners: [],
9
+ services: [],
10
+ containers: [],
11
+ interfaces: [],
12
+ filesystems: [],
13
+ kernel: {
14
+ contextSwitches: 0, contextSwitchRate: 0, interrupts: 0, interruptRate: 0,
15
+ forks: 0, forkRate: 0, procsRunning: 0, procsBlocked: 0, entropy: 0,
16
+ openFiles: 0, maxFiles: 0, bootTime: 0, pageIn: 0, pageOut: 0, swapIn: 0, swapOut: 0,
17
+ },
18
+ gpus: [],
19
+ power: null,
20
+ journal: [],
21
+ states: { running: 0, sleeping: 0, stopped: 0, zombie: 0, total: 0 },
22
+ connectionHistory: [],
23
+ sessionHistory: [],
24
+ protocols: [],
25
+ remotes: [],
26
+ inboundConnections: 0,
27
+ outboundConnections: 0,
28
+ net: {
29
+ tcpActiveOpens: 0, tcpPassiveOpens: 0, tcpEstablished: 0, tcpInSegs: 0,
30
+ tcpOutSegs: 0, tcpRetransSegs: 0, tcpInErrs: 0, tcpOutRsts: 0,
31
+ udpInDatagrams: 0, udpOutDatagrams: 0, udpInErrors: 0,
32
+ icmpInMsgs: 0, icmpOutMsgs: 0,
33
+ rates: { inSegs: 0, outSegs: 0, retrans: 0, passiveOpens: 0, activeOpens: 0, udpIn: 0, udpOut: 0 },
34
+ retransRatio: 0,
35
+ },
36
+ netInHistory: [],
37
+ netOutHistory: [],
38
+ retransHistory: [],
39
+ ssh: [],
40
+ http: null,
41
+ privileged: typeof process.getuid === "function" ? process.getuid() === 0 : false,
42
+ };
43
+ }
44
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/system/telemetry.ts"],"names":[],"mappings":"AAAA,iFAAiF;AA6NjF,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;QACV,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,EAAE;QACb,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;QACd,UAAU,EAAE,EAAE;QACd,WAAW,EAAE,EAAE;QACf,MAAM,EAAE;YACN,eAAe,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC;YACzE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;YACnE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;SACrF;QACD,IAAI,EAAE,EAAE;QACR,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;QACpE,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,EAAE;QAClB,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,kBAAkB,EAAE,CAAC;QACrB,mBAAmB,EAAE,CAAC;QACtB,GAAG,EAAE;YACH,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC;YACtE,UAAU,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;YAC7D,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;YACrD,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;YAC7B,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;YAClG,YAAY,EAAE,CAAC;SAChB;QACD,YAAY,EAAE,EAAE;QAChB,aAAa,EAAE,EAAE;QACjB,cAAc,EAAE,EAAE;QAClB,GAAG,EAAE,EAAE;QACP,IAAI,EAAE,IAAI;QACV,UAAU,EAAE,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK;KAClF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/hqtui-demo",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The HQTUI reference dashboard: a btop-grade terminal system monitor. Runs on real system metrics or a deterministic simulation.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,10 +22,11 @@
22
22
  "scripts": {
23
23
  "start": "bun src/main.ts",
24
24
  "build": "bun x tsc -p tsconfig.json",
25
- "prepublishOnly": "bun x tsc -p tsconfig.json"
25
+ "prepublishOnly": "bun x tsc -p tsconfig.json",
26
+ "shots": "bun scripts/shots.ts"
26
27
  },
27
28
  "dependencies": {
28
- "@profullstack/hqtui": "^0.1.1"
29
+ "@profullstack/hqtui": "^0.1.3"
29
30
  },
30
31
  "publishConfig": {
31
32
  "access": "public"
package/src/main.ts CHANGED
@@ -11,7 +11,8 @@ import { createApp, themeList, themes, type KeyEvent } from "@profullstack/hqtui
11
11
  import { createCollector } from "./system/index.ts";
12
12
  import { createState, SCREENS, type ScreenName } from "./state.ts";
13
13
  import {
14
- componentsScreen, dashboardScreen, graphicsScreen, inputScreen, stressScreen, themesScreen, visibleProcesses,
14
+ componentsScreen, dashboardScreen, graphicsScreen, inputScreen, networkScreen, servicesScreen,
15
+ sessionsScreen, stressScreen, themesScreen, trafficScreen, visibleProcesses,
15
16
  } from "./screens/index.ts";
16
17
  import { clock, num } from "./format.ts";
17
18
 
@@ -49,7 +50,7 @@ function parseArgs(argv: string[]): Options {
49
50
  case "-h":
50
51
  case "--help": printHelp(); process.exit(0);
51
52
  case "-v":
52
- case "--version": console.log("hqtui-demo 0.1.0"); process.exit(0);
53
+ case "--version": console.log("hqtui-demo 0.1.3"); process.exit(0);
53
54
  }
54
55
  }
55
56
  return options;
@@ -80,11 +81,15 @@ Keys:
80
81
 
81
82
  const PALETTE_COMMANDS: { label: string; hint: string; run: (state: ReturnType<typeof createState>) => void }[] = [
82
83
  { label: "Go to Dashboard", hint: "1", run: (s) => { s.screen = "dashboard"; } },
83
- { label: "Go to Components", hint: "2", run: (s) => { s.screen = "components"; } },
84
- { label: "Go to Graphics", hint: "3", run: (s) => { s.screen = "graphics"; } },
85
- { label: "Go to Themes", hint: "4", run: (s) => { s.screen = "themes"; } },
86
- { label: "Go to Input", hint: "5", run: (s) => { s.screen = "input"; } },
87
- { label: "Go to Stress Test", hint: "6", run: (s) => { s.screen = "stress"; } },
84
+ { label: "Go to Traffic", hint: "2", run: (s) => { s.screen = "traffic"; } },
85
+ { label: "Go to Sessions", hint: "3", run: (s) => { s.screen = "sessions"; } },
86
+ { label: "Go to Network", hint: "4", run: (s) => { s.screen = "network"; } },
87
+ { label: "Go to Services", hint: "5", run: (s) => { s.screen = "services"; } },
88
+ { label: "Go to Components", hint: "6", run: (s) => { s.screen = "components"; } },
89
+ { label: "Go to Graphics", hint: "7", run: (s) => { s.screen = "graphics"; } },
90
+ { label: "Go to Themes", hint: "8", run: (s) => { s.screen = "themes"; } },
91
+ { label: "Go to Input", hint: "9", run: (s) => { s.screen = "input"; } },
92
+ { label: "Go to Stress Test", hint: "0", run: (s) => { s.screen = "stress"; } },
88
93
  { label: "Sort by CPU", hint: "F6", run: (s) => { s.sort = "cpu"; } },
89
94
  { label: "Sort by Memory", hint: "F6", run: (s) => { s.sort = "mem"; } },
90
95
  { label: "Pause updates", hint: "Space", run: (s) => { s.paused = !s.paused; } },
@@ -220,8 +225,9 @@ async function main(): Promise<void> {
220
225
  }
221
226
 
222
227
  const digit = Number(event.name);
223
- if (Number.isInteger(digit) && digit >= 1 && digit <= SCREENS.length) {
224
- state.screen = SCREENS[digit - 1];
228
+ if (Number.isInteger(digit) && event.name.length === 1) {
229
+ const index = digit === 0 ? 9 : digit - 1;
230
+ if (index < SCREENS.length) state.screen = SCREENS[index];
225
231
  }
226
232
 
227
233
  // Keep the selected row inside the visible window.
@@ -232,7 +238,7 @@ async function main(): Promise<void> {
232
238
  ui.row({ size: 1 }, (header) => {
233
239
  header.text(" hqtui.com", { fg: theme.title, bold: true, size: 12 });
234
240
  header.tabs({
235
- tabs: SCREENS.map((s, i) => `${i + 1} ${s}`),
241
+ tabs: SCREENS.map((s, i) => `${(i + 1) % 10} ${s}`),
236
242
  active: SCREENS.indexOf(state.screen),
237
243
  onSelect: (index) => { state.screen = SCREENS[index]; },
238
244
  });
@@ -245,6 +251,10 @@ async function main(): Promise<void> {
245
251
 
246
252
  ui.column({ size: height - 4 }, (body) => {
247
253
  switch (state.screen) {
254
+ case "traffic": trafficScreen(body, state, theme); break;
255
+ case "sessions": sessionsScreen(body, state, theme); break;
256
+ case "network": networkScreen(body, state, theme); break;
257
+ case "services": servicesScreen(body, state, theme); break;
248
258
  case "components": componentsScreen(body, state, theme); break;
249
259
  case "graphics": graphicsScreen(body, state, theme); break;
250
260
  case "themes": themesScreen(body, state, theme); break;
@@ -280,7 +290,12 @@ async function main(): Promise<void> {
280
290
  "Arrows, PageUp/PageDown, Home/End move the selection.\n" +
281
291
  "Mouse: click tabs and buttons, scroll the process list.\n\n" +
282
292
  (state.unavailable.length
283
- ? `Unavailable on this platform: ${state.unavailable.join(", ")}.\nRun with --sim to see every widget populated.`
293
+ ? `Unavailable here: ${state.unavailable.join(", ")}.\n` +
294
+ (state.sample.telemetry.privileged
295
+ ? "Running as root: all privileged sources are readable."
296
+ : "Running unprivileged. sudo additionally unlocks socket process\n" +
297
+ "names, failed logins (btmp), HTTP access logs, per-process I/O\n" +
298
+ "and the full journal.")
284
299
  : "All metrics available on this platform.") +
285
300
  "\n\nPress any key to close.",
286
301
  buttons: [{ label: "Close", focused: true }],
@@ -1,4 +1,8 @@
1
1
  export { dashboardScreen, visibleProcesses } from "./dashboard.ts";
2
+ export { sessionsScreen } from "./sessions.ts";
3
+ export { networkScreen } from "./network.ts";
4
+ export { trafficScreen } from "./traffic.ts";
5
+ export { servicesScreen } from "./services.ts";
2
6
  export { componentsScreen } from "./components.ts";
3
7
  export { graphicsScreen } from "./graphics.ts";
4
8
  export { themesScreen } from "./themes.ts";
@@ -0,0 +1,91 @@
1
+ import type { Container, Theme } from "@profullstack/hqtui";
2
+ import type { DemoState } from "../state.ts";
3
+ import { byteRate, bytes } from "../format.ts";
4
+
5
+ /** Interfaces, live throughput, open connections and listening ports. */
6
+ export function networkScreen(ui: Container, state: DemoState, theme: Theme): void {
7
+ const t = state.sample.telemetry;
8
+ const active = t.interfaces.filter((i) => i.rxTotal > 0 || i.state === "up");
9
+ const shown = (active.length ? active : t.interfaces).slice(0, 3);
10
+
11
+ ui.row({ size: 13, gap: 1 }, (row) => {
12
+ if (shown.length === 0) {
13
+ row.panel({ title: "Interfaces" }, (p) => p.label("No interfaces reported."));
14
+ return;
15
+ }
16
+ shown.forEach((iface, index) => {
17
+ const color = [theme.primary, theme.success, theme.secondary][index % 3];
18
+ row.panel({
19
+ title: `${iface.name} (${iface.state})`,
20
+ subtitle: iface.ip,
21
+ borderColor: color,
22
+ }, (p) => {
23
+ p.row({ size: 1 }, (r) => {
24
+ r.text(`↓ ${byteRate(iface.rxRate)}`, { fg: theme.primary });
25
+ r.text(`↑ ${byteRate(iface.txRate)}`, { fg: theme.secondary, align: "right" });
26
+ });
27
+ p.graph({
28
+ series: [
29
+ { values: iface.rxHistory, color: theme.primary, fill: true },
30
+ { values: iface.txHistory, color: theme.secondary, fill: true },
31
+ ],
32
+ min: 0,
33
+ size: "1fr",
34
+ });
35
+ p.divider();
36
+ p.keyValues([
37
+ { label: "RX total", value: bytes(iface.rxTotal), color: theme.primary },
38
+ { label: "TX total", value: bytes(iface.txTotal), color: theme.secondary },
39
+ { label: "MAC", value: iface.mac, color: theme.muted },
40
+ { label: "MTU / err / drop", value: `${iface.mtu} / ${iface.errors} / ${iface.drops}`, color: theme.muted },
41
+ ]);
42
+ });
43
+ });
44
+ });
45
+
46
+ ui.row({ size: "1fr", gap: 1 }, (row) => {
47
+ row.panel({
48
+ title: "Connections",
49
+ subtitle: `${t.connections.length} open`,
50
+ borderColor: theme.accent,
51
+ }, (p) => {
52
+ if (t.connections.length === 0) {
53
+ p.label("No connections visible (`ss` unavailable).");
54
+ return;
55
+ }
56
+ p.table({
57
+ rows: t.connections,
58
+ selected: state.selected % Math.max(1, t.connections.length),
59
+ offset: state.offset,
60
+ zebra: true,
61
+ scrollbar: true,
62
+ columns: [
63
+ { key: "proto", title: "Proto", width: 6, color: theme.muted },
64
+ { key: "local", title: "Local", min: 18 },
65
+ { key: "remote", title: "Remote", min: 18, color: theme.accent },
66
+ { key: "state", title: "State", width: 10, color: theme.success },
67
+ { key: "process", title: "Process", min: 12, color: theme.primary },
68
+ ],
69
+ });
70
+ });
71
+
72
+ row.column({ width: "0.7fr", gap: 1 }, (column) => {
73
+ column.panel({ title: "Listening Ports", subtitle: String(t.listeners.length), borderColor: theme.warning }, (p) => {
74
+ p.table({
75
+ rows: t.listeners,
76
+ zebra: true,
77
+ scrollbar: true,
78
+ columns: [
79
+ { key: "proto", title: "Proto", width: 6, color: theme.muted },
80
+ { key: "port", title: "Port", width: 7, align: "right", color: theme.warning },
81
+ { key: "address", title: "Address", min: 10, color: theme.muted },
82
+ { key: "process", title: "Process", min: 10, color: theme.primary },
83
+ ],
84
+ });
85
+ });
86
+ column.panel({ title: "Open Connections", size: 6, borderColor: theme.secondary }, (p) => {
87
+ p.graph({ values: t.connectionHistory, min: 0, fill: true, color: theme.accent });
88
+ });
89
+ });
90
+ });
91
+ }