about-system 0.9.32 → 0.10.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/README.md CHANGED
@@ -121,6 +121,22 @@ about-system --json
121
121
  about-system --help
122
122
  ```
123
123
 
124
+ ### Web Dashboard
125
+
126
+ `about-system web` starts a small HTTP server with a React + [shadcn/ui](https://ui.shadcn.com) dashboard: usage bars for memory and disk, every info block grouped into cards, a filter box, light/dark mode, and auto-refresh every 10 seconds.
127
+
128
+ ```bash
129
+ about-system web # http://127.0.0.1:3777
130
+ about-system web --port 8080 # or PORT=8080 about-system web
131
+ about-system web --host 0.0.0.0 --port 8080 # reachable from other machines
132
+ ```
133
+
134
+ It listens on localhost by default. Pass `--host 0.0.0.0` to reach it on a remote server, but note that anyone who can reach the port sees the public IP, open ports, and running processes — prefer an SSH tunnel (`ssh -L 3777:localhost:3777 server`) or put it behind auth.
135
+
136
+ The page reads `GET /api/info`, which returns the same object as `about-system --json`.
137
+
138
+ To work on the dashboard itself (`web/`), run `about-system web` in one terminal and `bun run dev:web` in another — the Vite dev server proxies `/api` to port 3777.
139
+
124
140
  ### Installation as Shell Greeting
125
141
 
126
142
  ```bash
@@ -1,10 +1,84 @@
1
1
  #!/usr/bin/env node
2
- import y from "os";
3
- import r from "fs";
4
- import d from "path";
5
- import { fileURLToPath as P } from "url";
6
- import { g as F, a as I, b as S, C as b, S as k, c as p, d as v, D as $ } from "./system-info-api-C_y-O4VW.js";
7
- const x = P(import.meta.url), g = y.platform() === "win32", T = {
2
+ import S from "os";
3
+ import c from "fs";
4
+ import u from "path";
5
+ import { fileURLToPath as O } from "url";
6
+ import { g as $, a as T, b, C as j, S as k, c as g, d as B, D as I } from "./system-info-api-C_y-O4VW.js";
7
+ import A from "http";
8
+ const C = 3777, _ = "127.0.0.1", w = {
9
+ ".html": "text/html; charset=utf-8",
10
+ ".js": "text/javascript; charset=utf-8",
11
+ ".css": "text/css; charset=utf-8",
12
+ ".json": "application/json; charset=utf-8",
13
+ ".svg": "image/svg+xml",
14
+ ".png": "image/png",
15
+ ".ico": "image/x-icon",
16
+ ".woff2": "font/woff2"
17
+ };
18
+ function D() {
19
+ return u.join(u.dirname(O(import.meta.url)), "web");
20
+ }
21
+ function U(e, o) {
22
+ let t;
23
+ try {
24
+ t = decodeURIComponent(o.split("?")[0]);
25
+ } catch {
26
+ return null;
27
+ }
28
+ const s = u.resolve(e), n = u.resolve(s, "." + u.posix.normalize("/" + t));
29
+ if (n !== s && !n.startsWith(s + u.sep)) return null;
30
+ if (c.existsSync(n) && c.statSync(n).isFile()) return n;
31
+ const l = u.join(s, "index.html");
32
+ return c.existsSync(l) ? l : null;
33
+ }
34
+ function p(e, o, t, s) {
35
+ e.writeHead(o, {
36
+ "Content-Type": t,
37
+ "Cache-Control": "no-store",
38
+ "X-Content-Type-Options": "nosniff"
39
+ }), e.end(s);
40
+ }
41
+ function R(e = {}) {
42
+ const o = e.webRoot ?? D();
43
+ return A.createServer(async (t, s) => {
44
+ const n = t.url ?? "/";
45
+ if (t.method !== "GET" && t.method !== "HEAD") {
46
+ p(s, 405, "text/plain; charset=utf-8", "Method Not Allowed");
47
+ return;
48
+ }
49
+ if (n === "/api/info" || n.startsWith("/api/info?")) {
50
+ try {
51
+ const r = await $();
52
+ p(s, 200, w[".json"], JSON.stringify(r));
53
+ } catch (r) {
54
+ p(s, 500, w[".json"], JSON.stringify({ error: r.message }));
55
+ }
56
+ return;
57
+ }
58
+ const l = U(o, n);
59
+ if (!l) {
60
+ p(
61
+ s,
62
+ 404,
63
+ "text/plain; charset=utf-8",
64
+ "Dashboard not found. Build it with: npm run build:web"
65
+ );
66
+ return;
67
+ }
68
+ const i = w[u.extname(l)] ?? "application/octet-stream";
69
+ p(s, 200, i, c.readFileSync(l));
70
+ });
71
+ }
72
+ function H(e = {}) {
73
+ const o = e.port ?? C, t = e.host ?? _, s = R(e);
74
+ return new Promise((n, l) => {
75
+ s.once("error", l), s.listen(o, t, () => {
76
+ const i = s.address(), r = typeof i == "object" && i ? i.port : o;
77
+ n({ server: s, url: `http://${t === "0.0.0.0" || t === "::" ? "localhost" : t}:${r}` });
78
+ });
79
+ });
80
+ }
81
+ const z = O(import.meta.url), y = S.platform() === "win32", J = {
8
82
  31: [41, 97],
9
83
  // red
10
84
  32: [42, 30],
@@ -18,158 +92,158 @@ const x = P(import.meta.url), g = y.platform() === "win32", T = {
18
92
  36: [46, 30]
19
93
  // cyan
20
94
  };
21
- function j(e, s, o) {
22
- if (!s || s.trim() === "") return "";
23
- const l = o.display.show_backgrounds !== !1, n = o.colors[e], f = v[n], t = l && f || p[n] || p.reset, i = l ? p.reset : "", c = o.display.show_emojis && o.emojis[e] || "";
24
- if (e === "battery" && o.display.show_emojis) {
25
- const a = s.includes("+") ? o.emojis.battery_charging : o.emojis.battery;
26
- return `${t}${a}${s}${i}`;
95
+ function E(e, o, t) {
96
+ if (!o || o.trim() === "") return "";
97
+ const s = t.display.show_backgrounds !== !1, n = t.colors[e], l = B[n], i = s && l || g[n] || g.reset, r = s ? g.reset : "", a = t.display.show_emojis && t.emojis[e] || "";
98
+ if (e === "battery" && t.display.show_emojis) {
99
+ const f = o.includes("+") ? t.emojis.battery_charging : t.emojis.battery;
100
+ return `${i}${f}${o}${r}`;
27
101
  }
28
- if (e === "ports" && o.colors[e] === "multicolor" && s) {
29
- let u = ` ${o.display.show_emojis ? o.emojis.ports : ""}`;
30
- const m = s.split(" "), h = [31, 32, 33, 34, 35, 36];
31
- return m.forEach((w, O) => {
32
- const _ = h[O % h.length];
33
- if (l) {
34
- const [E, L] = T[_];
35
- u += `\x1B[${E}m\x1B[${L}m${w}\x1B[0m `;
102
+ if (e === "ports" && t.colors[e] === "multicolor" && o) {
103
+ let h = ` ${t.display.show_emojis ? t.emojis.ports : ""}`;
104
+ const d = o.split(" "), m = [31, 32, 33, 34, 35, 36];
105
+ return d.forEach((v, L) => {
106
+ const x = m[L % m.length];
107
+ if (s) {
108
+ const [W, N] = J[x];
109
+ h += `\x1B[${W}m\x1B[${N}m${v}\x1B[0m `;
36
110
  } else
37
- u += `\x1B[${_}m${w}\x1B[0m `;
38
- }), u.trim();
111
+ h += `\x1B[${x}m${v}\x1B[0m `;
112
+ }), h.trim();
39
113
  }
40
- if (e === "pacman" && o.colors[e] === "multicolor" && s) {
41
- const a = o.display.show_emojis ? o.emojis.pacman : "";
42
- return `${t}${a}${s}${i}`;
114
+ if (e === "pacman" && t.colors[e] === "multicolor" && o) {
115
+ const f = t.display.show_emojis ? t.emojis.pacman : "";
116
+ return `${i}${f}${o}${r}`;
43
117
  }
44
- return `${t}${c}${s}${i}`;
118
+ return `${i}${a}${o}${r}`;
45
119
  }
46
- function B(e, s) {
47
- if (s <= 0) return e ? [e] : [];
48
- const o = [];
49
- let l = "", n = 0, f = "";
50
- for (let t = 0; t < e.length; t++) {
51
- const i = e[t];
52
- if (i === "\x1B" && e[t + 1] === "[") {
53
- let m = i, h = t + 1;
54
- for (; h < e.length && e[h] !== "m"; )
55
- m += e[h], h++;
56
- h < e.length && (m += e[h]), l += m, f = /\x1b\[0m/.test(m) ? "" : m, t = h;
120
+ function G(e, o) {
121
+ if (o <= 0) return e ? [e] : [];
122
+ const t = [];
123
+ let s = "", n = 0, l = "";
124
+ for (let i = 0; i < e.length; i++) {
125
+ const r = e[i];
126
+ if (r === "\x1B" && e[i + 1] === "[") {
127
+ let d = r, m = i + 1;
128
+ for (; m < e.length && e[m] !== "m"; )
129
+ d += e[m], m++;
130
+ m < e.length && (d += e[m]), s += d, l = /\x1b\[0m/.test(d) ? "" : d, i = m;
57
131
  continue;
58
132
  }
59
- let c = i, a = 1;
60
- const u = e.charCodeAt(t);
61
- u >= 55296 && u <= 56319 && t + 1 < e.length && (c = i + e[t + 1], a = 2, t++), n >= s && (o.push(l), l = f, n = 0), l += c, n += a;
133
+ let a = r, f = 1;
134
+ const h = e.charCodeAt(i);
135
+ h >= 55296 && h <= 56319 && i + 1 < e.length && (a = r + e[i + 1], f = 2, i++), n >= o && (t.push(s), s = l, n = 0), s += a, n += f;
62
136
  }
63
- return l && o.push(l), o;
137
+ return s && t.push(s), t;
64
138
  }
65
- async function C(e = null) {
66
- const s = I(), o = e || s.display_order, l = await F();
67
- if (s.display.single_line) {
68
- const i = [];
69
- for (const c of o)
70
- for (const a of c) {
71
- const u = l[a], m = j(a, u, s);
72
- m && m.trim() && i.push(m);
139
+ async function F(e = null) {
140
+ const o = T(), t = e || o.display_order, s = await $();
141
+ if (o.display.single_line) {
142
+ const r = [];
143
+ for (const a of t)
144
+ for (const f of a) {
145
+ const h = s[f], d = E(f, h, o);
146
+ d && d.trim() && r.push(d);
73
147
  }
74
- i.length > 0 && console.log(i.join(" ") + p.reset);
148
+ r.length > 0 && console.log(r.join(" ") + g.reset);
75
149
  return;
76
150
  }
77
- const n = s.display.line_wrap_length, f = [];
78
- for (const i of o)
79
- for (const c of i) {
80
- const a = l[c], u = j(c, a, s);
81
- u && u.trim() && f.push(u);
151
+ const n = o.display.line_wrap_length, l = [];
152
+ for (const r of t)
153
+ for (const a of r) {
154
+ const f = s[a], h = E(a, f, o);
155
+ h && h.trim() && l.push(h);
82
156
  }
83
- const t = B(f.join(" "), n);
84
- t.length > 0 ? t.forEach((i) => {
85
- console.log(i + p.reset);
86
- }) : s.advanced.debug && console.log("No system information could be displayed");
157
+ const i = G(l.join(" "), n);
158
+ i.length > 0 ? i.forEach((r) => {
159
+ console.log(r + g.reset);
160
+ }) : o.advanced.debug && console.log("No system information could be displayed");
87
161
  }
88
- function N(e) {
89
- const s = I();
162
+ function M(e) {
163
+ const o = T();
90
164
  if (e.includes("--settings-init"))
91
- return S($) ? console.log("Settings initialized with defaults") : console.log("Failed to initialize settings"), !0;
165
+ return b(I) ? console.log("Settings initialized with defaults") : console.log("Failed to initialize settings"), !0;
92
166
  if (e.includes("--settings-show"))
93
- return console.log("Current settings:"), console.log(JSON.stringify(s, null, 2)), !0;
167
+ return console.log("Current settings:"), console.log(JSON.stringify(o, null, 2)), !0;
94
168
  if (e.includes("--settings-reset"))
95
- return S($) ? console.log("Settings reset to defaults") : console.log("Failed to reset settings"), !0;
169
+ return b(I) ? console.log("Settings reset to defaults") : console.log("Failed to reset settings"), !0;
96
170
  if (e.includes("--refresh")) {
97
171
  try {
98
- r.existsSync(b) && (r.unlinkSync(b), console.log("Cache cleared"));
99
- } catch (l) {
100
- console.error("Error clearing cache:", l.message);
172
+ c.existsSync(j) && (c.unlinkSync(j), console.log("Cache cleared"));
173
+ } catch (s) {
174
+ console.error("Error clearing cache:", s.message);
101
175
  }
102
176
  return !0;
103
177
  }
104
- const o = e.indexOf("--set");
105
- if (o !== -1 && e[o + 1] && e[o + 2]) {
106
- const l = e[o + 1], n = e[o + 2];
178
+ const t = e.indexOf("--set");
179
+ if (t !== -1 && e[t + 1] && e[t + 2]) {
180
+ const s = e[t + 1], n = e[t + 2];
107
181
  try {
108
- const f = n.startsWith("{") || n.startsWith("[") ? JSON.parse(n) : n === "true" ? !0 : n === "false" ? !1 : n, t = l.split(".");
109
- let i = s;
110
- for (let c = 0; c < t.length - 1; c++)
111
- i[t[c]] || (i[t[c]] = {}), i = i[t[c]];
112
- i[t[t.length - 1]] = f, S(s) ? console.log(`Setting ${l} = ${n}`) : console.log("Failed to save settings");
113
- } catch (f) {
114
- console.error("Error setting value:", f.message);
182
+ const l = n.startsWith("{") || n.startsWith("[") ? JSON.parse(n) : n === "true" ? !0 : n === "false" ? !1 : n, i = s.split(".");
183
+ let r = o;
184
+ for (let a = 0; a < i.length - 1; a++)
185
+ r[i[a]] || (r[i[a]] = {}), r = r[i[a]];
186
+ r[i[i.length - 1]] = l, b(o) ? console.log(`Setting ${s} = ${n}`) : console.log("Failed to save settings");
187
+ } catch (l) {
188
+ console.error("Error setting value:", l.message);
115
189
  }
116
190
  return !0;
117
191
  }
118
192
  return !1;
119
193
  }
120
- function D() {
121
- const e = y.homedir();
122
- let s, o;
123
- g ? (s = d.join(e, "AppData", "Local"), o = d.join(s, "systeminfo")) : (s = d.join(e, ".config"), o = d.join(s, "systeminfo"));
124
- const l = d.resolve(x);
194
+ function V() {
195
+ const e = S.homedir();
196
+ let o, t;
197
+ y ? (o = u.join(e, "AppData", "Local"), t = u.join(o, "systeminfo")) : (o = u.join(e, ".config"), t = u.join(o, "systeminfo"));
198
+ const s = u.resolve(z);
125
199
  try {
126
- if (r.existsSync(s) || r.mkdirSync(s, { recursive: !0 }), r.copyFileSync(l, o), g || r.chmodSync(o, "755"), g) {
127
- console.log("Windows installation:"), console.log("1. Script copied to:", o), console.log("2. To add to PowerShell profile, run:"), console.log(` Add-Content $PROFILE "node '${o}'"`), console.log(
200
+ if (c.existsSync(o) || c.mkdirSync(o, { recursive: !0 }), c.copyFileSync(s, t), y || c.chmodSync(t, "755"), y) {
201
+ console.log("Windows installation:"), console.log("1. Script copied to:", t), console.log("2. To add to PowerShell profile, run:"), console.log(` Add-Content $PROFILE "node '${t}'"`), console.log(
128
202
  "3. To add to Command Prompt, create a batch file in your startup folder"
129
203
  );
130
- const n = d.join(s, "systeminfo-startup.bat");
131
- r.writeFileSync(n, `@echo off
132
- node "${o}"
204
+ const n = u.join(o, "systeminfo-startup.bat");
205
+ c.writeFileSync(n, `@echo off
206
+ node "${t}"
133
207
  `), console.log("4. Batch file created:", n);
134
208
  } else {
135
209
  try {
136
- const a = d.join(e, ".hushlogin");
137
- r.writeFileSync(a, "");
210
+ const f = u.join(e, ".hushlogin");
211
+ c.writeFileSync(f, "");
138
212
  } catch {
139
213
  }
140
- const n = d.join(e, ".bashrc"), f = `node ${o}`;
141
- r.existsSync(n) ? r.readFileSync(n, "utf8").includes("systeminfo") || r.appendFileSync(n, `
142
- ${f}
143
- `) : r.writeFileSync(n, `${f}
214
+ const n = u.join(e, ".bashrc"), l = `node ${t}`;
215
+ c.existsSync(n) ? c.readFileSync(n, "utf8").includes("systeminfo") || c.appendFileSync(n, `
216
+ ${l}
217
+ `) : c.writeFileSync(n, `${l}
144
218
  `);
145
- const t = d.join(e, ".zshrc");
146
- r.existsSync(t) && (r.readFileSync(t, "utf8").includes("systeminfo") || r.appendFileSync(t, `
147
- ${f}
219
+ const i = u.join(e, ".zshrc");
220
+ c.existsSync(i) && (c.readFileSync(i, "utf8").includes("systeminfo") || c.appendFileSync(i, `
221
+ ${l}
148
222
  `));
149
- const i = d.join(
223
+ const r = u.join(
150
224
  e,
151
225
  ".config",
152
226
  "fish",
153
227
  "config.fish"
154
228
  );
155
- r.existsSync(i) && (r.readFileSync(i, "utf8").includes("systeminfo") || r.appendFileSync(
156
- i,
229
+ c.existsSync(r) && (c.readFileSync(r, "utf8").includes("systeminfo") || c.appendFileSync(
230
+ r,
157
231
  `
158
232
  set -U fish_greeting ""
159
- ${f}
233
+ ${l}
160
234
  `
161
235
  ));
162
- const c = d.join(
236
+ const a = u.join(
163
237
  e,
164
238
  ".config",
165
239
  "nushell",
166
240
  "config.nu"
167
241
  );
168
- r.existsSync(c) && (r.readFileSync(c, "utf8").includes("systeminfo") || r.appendFileSync(
169
- c,
242
+ c.existsSync(a) && (c.readFileSync(a, "utf8").includes("systeminfo") || c.appendFileSync(
243
+ a,
170
244
  `
171
245
  $env.config.show_banner = false
172
- ${f}
246
+ ${l}
173
247
  `
174
248
  ));
175
249
  }
@@ -178,22 +252,36 @@ ${f}
178
252
  console.error("Error installing shell greeting:", n.message), process.exit(1);
179
253
  }
180
254
  }
181
- function A(e) {
182
- for (const s of e)
183
- if (!s.startsWith("--") && s.includes(","))
184
- return s.split(",").map((o) => o.trim()).filter((o) => o.length > 0);
185
- for (const s of e)
186
- if (!s.startsWith("--") && !s.includes("=") && s.length > 0)
187
- return [s.trim()];
255
+ function P(e, o) {
256
+ for (let t = 0; t < e.length; t++) {
257
+ if (e[t] === o) return e[t + 1];
258
+ if (e[t].startsWith(o + "=")) return e[t].slice(o.length + 1);
259
+ }
260
+ }
261
+ async function X(e) {
262
+ const o = P(e, "--port") ?? process.env.PORT, t = o === void 0 ? C : Number(o);
263
+ if (!Number.isInteger(t) || t < 0 || t > 65535)
264
+ throw new Error(`Invalid port: ${o}`);
265
+ const s = P(e, "--host") ?? _, { url: n } = await H({ port: t, host: s });
266
+ console.log(`About System web UI running at ${n}`), console.log(s === _ ? "Listening on localhost only. Use --host 0.0.0.0 to expose it on the network." : "Warning: system details (public IP, ports, processes) are visible to anyone who can reach this port."), console.log("Press Ctrl+C to stop.");
267
+ }
268
+ function Y(e) {
269
+ for (const o of e)
270
+ if (!o.startsWith("--") && o.includes(","))
271
+ return o.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
272
+ for (const o of e)
273
+ if (!o.startsWith("--") && !o.includes("=") && o.length > 0)
274
+ return [o.trim()];
188
275
  return null;
189
276
  }
190
- async function W() {
277
+ async function K() {
191
278
  console.log(`
192
279
  System Info Script - TypeScript Version
193
280
 
194
281
  Usage:
195
282
  about-system [options]
196
283
  about-system <part1,part2,...> # CLI mode: show specific parts only
284
+ about-system web [--port N] [--host H] # Serve the web dashboard
197
285
 
198
286
  Options:
199
287
  --help, -h Show this help message
@@ -217,11 +305,13 @@ Examples:
217
305
  about-system --set emojis.cpu "🚀 "
218
306
  about-system --set labels.cpu "Processor"
219
307
  about-system --json
308
+ about-system web # http://127.0.0.1:${C}
309
+ about-system web --port 8080 --host 0.0.0.0
220
310
 
221
311
  Settings file: ${k}
222
- Cache file: ${b}
312
+ Cache file: ${j}
223
313
 
224
- Platform: ${g ? "Windows" : y.platform() === "darwin" ? "macOS" : y.platform() === "linux" ? "Linux" : "Unknown"}
314
+ Platform: ${y ? "Windows" : S.platform() === "darwin" ? "macOS" : S.platform() === "linux" ? "Linux" : "Unknown"}
225
315
 
226
316
  Available display blocks:
227
317
  Basic: user, hostname, uptime, shell, os, kernel, device
@@ -232,35 +322,39 @@ Available display blocks:
232
322
  Tools: pacman, ports, containers
233
323
  `);
234
324
  }
235
- async function z() {
325
+ async function Q() {
236
326
  const e = process.argv.slice(2);
237
- if (N(e))
327
+ if (M(e))
238
328
  return;
239
329
  if (e.includes("--help") || e.includes("-h")) {
240
- await W();
330
+ await K();
241
331
  return;
242
332
  }
243
333
  if (e.includes("--install")) {
244
- D();
334
+ V();
335
+ return;
336
+ }
337
+ if (e[0] === "web" || e.includes("--web")) {
338
+ await X(e);
245
339
  return;
246
340
  }
247
341
  if (e.includes("--json")) {
248
- const o = await F();
249
- console.log(JSON.stringify(o, null, 2));
342
+ const t = await $();
343
+ console.log(JSON.stringify(t, null, 2));
250
344
  return;
251
345
  }
252
- const s = A(e);
253
- if (s) {
254
- await C([s]);
346
+ const o = Y(e);
347
+ if (o) {
348
+ await F([o]);
255
349
  return;
256
350
  }
257
- await C();
351
+ await F();
258
352
  }
259
- z().catch((e) => {
353
+ Q().catch((e) => {
260
354
  console.error("Error:", e.message), process.exit(1);
261
355
  });
262
356
  export {
263
- C as displaySystemInfo,
264
- D as installShellGreeting
357
+ F as displaySystemInfo,
358
+ V as installShellGreeting
265
359
  };
266
360
  //# sourceMappingURL=about-system-cli.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"about-system-cli.js","sources":["../src/about-system-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport os from \"os\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { getSystemInfo } from \"./system-info-api\";\nimport type { SystemInfo, SystemInfoOptions } from \"./systeminfo-types\";\n\nconst __filename = fileURLToPath(import.meta.url);\n\nimport {\n Settings,\n DEFAULT_SETTINGS,\n colors,\n backgrounds,\n SETTINGS_FILE,\n CACHE_FILE,\n loadSettings,\n saveSettings,\n} from \"./info/settings\";\n\n// Platform detection\nconst IS_WINDOWS = os.platform() === \"win32\";\n\n// Foreground code -> [background code, contrasting text code] for the\n// legacy 8-color multicolor rotation (ports/pacman rainbow mode).\nconst MULTICOLOR_BG: Record<number, [number, number]> = {\n 31: [41, 97], // red\n 32: [42, 30], // green\n 33: [43, 30], // yellow\n 34: [44, 97], // blue\n 35: [45, 97], // magenta\n 36: [46, 30], // cyan\n};\n\nfunction formatValue(key: string, value: string, settings: Settings): string {\n if (!value || value.trim() === \"\") return \"\";\n\n const showBackgrounds = settings.display.show_backgrounds !== false;\n const colorName = settings.colors[key] as keyof typeof colors;\n const bg = backgrounds[colorName as keyof typeof backgrounds];\n const style = (showBackgrounds && bg) || colors[colorName] || colors.reset;\n const suffix = showBackgrounds ? colors.reset : \"\";\n const emoji = settings.display.show_emojis ? settings.emojis[key] || \"\" : \"\";\n\n // Special handling for battery emoji\n if (key === \"battery\" && settings.display.show_emojis) {\n const batteryEmoji = value.includes(\"+\")\n ? settings.emojis.battery_charging\n : settings.emojis.battery;\n return `${style}${batteryEmoji}${value}${suffix}`;\n }\n\n // Multicolor handling for ports\n if (key === \"ports\" && settings.colors[key] === \"multicolor\" && value) {\n const emoji = settings.display.show_emojis ? settings.emojis.ports : \"\";\n let output = ` ${emoji}`;\n const ports = value.split(\" \");\n const colorCodes = [31, 32, 33, 34, 35, 36];\n ports.forEach((port, index) => {\n const colorCode = colorCodes[index % colorCodes.length];\n if (showBackgrounds) {\n const [bgCode, textCode] = MULTICOLOR_BG[colorCode];\n output += `\\x1b[${bgCode}m\\x1b[${textCode}m${port}\\x1b[0m `;\n } else {\n output += `\\x1b[${colorCode}m${port}\\x1b[0m `;\n }\n });\n return output.trim();\n }\n\n // Multicolor handling for pacman\n if (key === \"pacman\" && settings.colors[key] === \"multicolor\" && value) {\n const emoji = settings.display.show_emojis ? settings.emojis.pacman : \"\";\n return `${style}${emoji}${value}${suffix}`;\n }\n\n return `${style}${emoji}${value}${suffix}`;\n}\n\n/**\n * Wraps text to a maximum visible width, filling each line completely with\n * characters before moving on. Unlike block-boundary wrapping, this breaks in\n * the middle of an info block when it doesn't fit, so no visible space is left\n * unused at the end of a line.\n *\n * ANSI color codes are copied verbatim and never counted toward the width, and\n * the active color is re-applied at the start of each wrapped line so colors\n * survive a mid-block break. Emoji surrogate pairs are kept intact.\n *\n * @param text - The text to wrap (may contain ANSI escape sequences)\n * @param maxLength - Maximum visible characters per line\n * @returns Array of wrapped lines\n */\nfunction wrapAnsiText(text: string, maxLength: number): string[] {\n if (maxLength <= 0) return text ? [text] : [];\n\n const lines: string[] = [];\n let currentLine = \"\";\n let visibleCount = 0;\n let activeAnsi = \"\";\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n\n // Copy ANSI escape sequences verbatim without counting them.\n if (char === \"\\x1b\" && text[i + 1] === \"[\") {\n let seq = char;\n let j = i + 1;\n while (j < text.length && text[j] !== \"m\") {\n seq += text[j];\n j++;\n }\n if (j < text.length) seq += text[j]; // include the trailing \"m\"\n currentLine += seq;\n // Track the active color so wrapped lines keep it; a reset clears it.\n activeAnsi = /\\x1b\\[0m/.test(seq) ? \"\" : seq;\n i = j;\n continue;\n }\n\n // Keep an emoji (surrogate pair) together and count it as width 2.\n let unit = char;\n let width = 1;\n const code = text.charCodeAt(i);\n if (code >= 0xd800 && code <= 0xdbff && i + 1 < text.length) {\n unit = char + text[i + 1];\n width = 2;\n i++;\n }\n\n // Line is full: break here, even in the middle of an info block.\n if (visibleCount >= maxLength) {\n lines.push(currentLine);\n currentLine = activeAnsi;\n visibleCount = 0;\n }\n\n currentLine += unit;\n visibleCount += width;\n }\n\n if (currentLine) lines.push(currentLine);\n\n return lines;\n}\n\nasync function displaySystemInfo(\n customDisplayOrder: string[][] | null = null\n): Promise<void> {\n const settings = loadSettings();\n const displayOrder = customDisplayOrder || settings.display_order;\n\n // Get system info\n const info = await getSystemInfo();\n\n // Single line mode\n if (settings.display.single_line) {\n const allItems: string[] = [];\n\n for (const group of displayOrder) {\n for (const key of group) {\n const value = info[key as keyof SystemInfo] as string;\n const formatted = formatValue(key, value, settings);\n if (formatted && formatted.trim()) {\n allItems.push(formatted);\n }\n }\n }\n\n if (allItems.length > 0) {\n console.log(allItems.join(\" \") + colors.reset);\n }\n return;\n }\n\n // Multi-line mode: fill each line completely with characters, wrapping in\n // the middle of an info block when it no longer fits.\n const maxLineLength = settings.display.line_wrap_length;\n const allItems: string[] = [];\n\n for (const group of displayOrder) {\n for (const key of group) {\n const value = info[key as keyof SystemInfo] as string;\n const formatted = formatValue(key, value, settings);\n\n if (formatted && formatted.trim()) {\n allItems.push(formatted);\n }\n }\n }\n\n const lines = wrapAnsiText(allItems.join(\" \"), maxLineLength);\n\n // Output\n if (lines.length > 0) {\n lines.forEach((line) => {\n console.log(line + colors.reset);\n });\n } else if (settings.advanced.debug) {\n console.log(\"No system information could be displayed\");\n }\n}\n\nfunction handleSettingsCommand(args: string[]): boolean {\n const settings = loadSettings();\n\n if (args.includes(\"--settings-init\")) {\n if (saveSettings(DEFAULT_SETTINGS)) {\n console.log(\"Settings initialized with defaults\");\n } else {\n console.log(\"Failed to initialize settings\");\n }\n return true;\n }\n\n if (args.includes(\"--settings-show\")) {\n console.log(\"Current settings:\");\n console.log(JSON.stringify(settings, null, 2));\n return true;\n }\n\n if (args.includes(\"--settings-reset\")) {\n if (saveSettings(DEFAULT_SETTINGS)) {\n console.log(\"Settings reset to defaults\");\n } else {\n console.log(\"Failed to reset settings\");\n }\n return true;\n }\n\n if (args.includes(\"--refresh\")) {\n try {\n if (fs.existsSync(CACHE_FILE)) {\n fs.unlinkSync(CACHE_FILE);\n console.log(\"Cache cleared\");\n }\n } catch (error) {\n console.error(\"Error clearing cache:\", (error as Error).message);\n }\n return true;\n }\n\n const setIndex = args.indexOf(\"--set\");\n if (setIndex !== -1 && args[setIndex + 1] && args[setIndex + 2]) {\n const key = args[setIndex + 1];\n const value = args[setIndex + 2];\n\n try {\n const parsedValue =\n value.startsWith(\"{\") || value.startsWith(\"[\")\n ? JSON.parse(value)\n : value === \"true\"\n ? true\n : value === \"false\"\n ? false\n : value;\n\n const keys = key.split(\".\");\n let current: any = settings;\n for (let i = 0; i < keys.length - 1; i++) {\n if (!current[keys[i]]) current[keys[i]] = {};\n current = current[keys[i]];\n }\n current[keys[keys.length - 1]] = parsedValue;\n\n if (saveSettings(settings)) {\n console.log(`Setting ${key} = ${value}`);\n } else {\n console.log(\"Failed to save settings\");\n }\n } catch (error) {\n console.error(\"Error setting value:\", (error as Error).message);\n }\n return true;\n }\n\n return false;\n}\n\nfunction installShellGreeting(): void {\n const homeDir = os.homedir();\n\n let configDir: string, scriptPath: string;\n if (IS_WINDOWS) {\n configDir = path.join(homeDir, \"AppData\", \"Local\");\n scriptPath = path.join(configDir, \"systeminfo\");\n } else {\n configDir = path.join(homeDir, \".config\");\n scriptPath = path.join(configDir, \"systeminfo\");\n }\n\n const currentScript = path.resolve(__filename);\n\n try {\n if (!fs.existsSync(configDir)) {\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n fs.copyFileSync(currentScript, scriptPath);\n if (!IS_WINDOWS) {\n fs.chmodSync(scriptPath, \"755\");\n }\n\n if (IS_WINDOWS) {\n console.log(\"Windows installation:\");\n console.log(\"1. Script copied to:\", scriptPath);\n console.log(\"2. To add to PowerShell profile, run:\");\n console.log(` Add-Content $PROFILE \"node '${scriptPath}'\"`);\n console.log(\n \"3. To add to Command Prompt, create a batch file in your startup folder\"\n );\n\n const startupBat = path.join(configDir, \"systeminfo-startup.bat\");\n fs.writeFileSync(startupBat, `@echo off\\nnode \"${scriptPath}\"\\n`);\n console.log(\"4. Batch file created:\", startupBat);\n } else {\n try {\n const hushLoginPath = path.join(homeDir, \".hushlogin\");\n fs.writeFileSync(hushLoginPath, \"\");\n } catch {}\n\n const bashrcPath = path.join(homeDir, \".bashrc\");\n const bashLine = `node ${scriptPath}`;\n\n if (fs.existsSync(bashrcPath)) {\n const bashrc = fs.readFileSync(bashrcPath, \"utf8\");\n if (!bashrc.includes(\"systeminfo\")) {\n fs.appendFileSync(bashrcPath, `\\n${bashLine}\\n`);\n }\n } else {\n fs.writeFileSync(bashrcPath, `${bashLine}\\n`);\n }\n\n const zshrcPath = path.join(homeDir, \".zshrc\");\n if (fs.existsSync(zshrcPath)) {\n const zshrc = fs.readFileSync(zshrcPath, \"utf8\");\n if (!zshrc.includes(\"systeminfo\")) {\n fs.appendFileSync(zshrcPath, `\\n${bashLine}\\n`);\n }\n }\n\n const fishConfigPath = path.join(\n homeDir,\n \".config\",\n \"fish\",\n \"config.fish\"\n );\n if (fs.existsSync(fishConfigPath)) {\n const fishConfig = fs.readFileSync(fishConfigPath, \"utf8\");\n if (!fishConfig.includes(\"systeminfo\")) {\n fs.appendFileSync(\n fishConfigPath,\n `\\nset -U fish_greeting \"\"\\n${bashLine}\\n`\n );\n }\n }\n\n const nushellConfigPath = path.join(\n homeDir,\n \".config\",\n \"nushell\",\n \"config.nu\"\n );\n if (fs.existsSync(nushellConfigPath)) {\n const nushellConfig = fs.readFileSync(nushellConfigPath, \"utf8\");\n if (!nushellConfig.includes(\"systeminfo\")) {\n fs.appendFileSync(\n nushellConfigPath,\n `\\n$env.config.show_banner = false\\n${bashLine}\\n`\n );\n }\n }\n }\n\n console.log(\"Shell greeting installation completed!\");\n } catch (error) {\n console.error(\"Error installing shell greeting:\", (error as Error).message);\n process.exit(1);\n }\n}\n\nfunction parseCLIMode(args: string[]): string[] | null {\n for (const arg of args) {\n if (!arg.startsWith(\"--\") && arg.includes(\",\")) {\n return arg\n .split(\",\")\n .map((part) => part.trim())\n .filter((part) => part.length > 0);\n }\n }\n\n for (const arg of args) {\n if (!arg.startsWith(\"--\") && !arg.includes(\"=\") && arg.length > 0) {\n return [arg.trim()];\n }\n }\n\n return null;\n}\n\nasync function showHelp(): Promise<void> {\n console.log(`\nSystem Info Script - TypeScript Version\n\nUsage:\n about-system [options]\n about-system <part1,part2,...> # CLI mode: show specific parts only\n\nOptions:\n --help, -h Show this help message\n --install Install as shell greeting\n --settings-init Initialize settings file with defaults\n --settings-show Display current settings\n --settings-reset Reset settings to defaults\n --refresh Clear the cache file\n --set <key> <value> Set a configuration value (use dot notation)\n --json Output as JSON\n\nExamples:\n about-system # Show all info (default)\n about-system cpu,os # Show only CPU and OS info\n about-system user,hostname,ip # Show user, hostname, and IP\n about-system disk_used # Show only disk usage\n about-system --install\n about-system --set display.show_emojis false\n about-system --set display.show_backgrounds false\n about-system --set colors.user blue\n about-system --set emojis.cpu \"🚀 \"\n about-system --set labels.cpu \"Processor\"\n about-system --json\n\nSettings file: ${SETTINGS_FILE}\nCache file: ${CACHE_FILE}\n\nPlatform: ${\n IS_WINDOWS\n ? \"Windows\"\n : os.platform() === \"darwin\"\n ? \"macOS\"\n : os.platform() === \"linux\"\n ? \"Linux\"\n : \"Unknown\"\n }\n\nAvailable display blocks:\n Basic: user, hostname, uptime, shell, os, kernel, device\n Resources: disk_used, ram_used, memory_available, swap_used, top_process\n Network: ip, iplocal, city, domain, isp, network_interfaces\n Hardware: cpu, gpu, temperature, battery, screen_resolution\n System: load_average, users_logged_in, mount_points, services_running\n Tools: pacman, ports, containers\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n if (handleSettingsCommand(args)) {\n return;\n }\n\n if (args.includes(\"--help\") || args.includes(\"-h\")) {\n await showHelp();\n return;\n }\n\n if (args.includes(\"--install\")) {\n installShellGreeting();\n return;\n }\n\n if (args.includes(\"--json\")) {\n const info = await getSystemInfo();\n console.log(JSON.stringify(info, null, 2));\n return;\n }\n\n const cliParts = parseCLIMode(args);\n if (cliParts) {\n const customDisplayOrder = [cliParts];\n await displaySystemInfo(customDisplayOrder);\n return;\n }\n\n await displaySystemInfo();\n}\n\nmain().catch((error) => {\n console.error(\"Error:\", error.message);\n process.exit(1);\n});\n\nexport { displaySystemInfo, installShellGreeting };\n"],"names":["__filename","fileURLToPath","IS_WINDOWS","os","MULTICOLOR_BG","formatValue","key","value","settings","showBackgrounds","colorName","bg","backgrounds","style","colors","suffix","emoji","batteryEmoji","output","ports","colorCodes","port","index","colorCode","bgCode","textCode","wrapAnsiText","text","maxLength","lines","currentLine","visibleCount","activeAnsi","i","char","seq","j","unit","width","code","displaySystemInfo","customDisplayOrder","loadSettings","displayOrder","info","getSystemInfo","allItems","group","formatted","maxLineLength","line","handleSettingsCommand","args","saveSettings","DEFAULT_SETTINGS","fs","CACHE_FILE","error","setIndex","parsedValue","keys","current","installShellGreeting","homeDir","configDir","scriptPath","path","currentScript","startupBat","hushLoginPath","bashrcPath","bashLine","zshrcPath","fishConfigPath","nushellConfigPath","parseCLIMode","arg","part","showHelp","SETTINGS_FILE","main","cliParts"],"mappings":";;;;;;AAQA,MAAMA,IAAaC,EAAc,YAAY,GAAG,GAc1CC,IAAaC,EAAG,SAAA,MAAe,SAI/BC,IAAkD;AAAA,EACtD,IAAI,CAAC,IAAI,EAAE;AAAA;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA;AAAA,EACX,IAAI,CAAC,IAAI,EAAE;AAAA;AACb;AAEA,SAASC,EAAYC,GAAaC,GAAeC,GAA4B;AAC3E,MAAI,CAACD,KAASA,EAAM,KAAA,MAAW,GAAI,QAAO;AAE1C,QAAME,IAAkBD,EAAS,QAAQ,qBAAqB,IACxDE,IAAYF,EAAS,OAAOF,CAAG,GAC/BK,IAAKC,EAAYF,CAAqC,GACtDG,IAASJ,KAAmBE,KAAOG,EAAOJ,CAAS,KAAKI,EAAO,OAC/DC,IAASN,IAAkBK,EAAO,QAAQ,IAC1CE,IAAQR,EAAS,QAAQ,eAAcA,EAAS,OAAOF,CAAG,KAAK;AAGrE,MAAIA,MAAQ,aAAaE,EAAS,QAAQ,aAAa;AACrD,UAAMS,IAAeV,EAAM,SAAS,GAAG,IACnCC,EAAS,OAAO,mBAChBA,EAAS,OAAO;AACpB,WAAO,GAAGK,CAAK,GAAGI,CAAY,GAAGV,CAAK,GAAGQ,CAAM;AAAA,EACjD;AAGA,MAAIT,MAAQ,WAAWE,EAAS,OAAOF,CAAG,MAAM,gBAAgBC,GAAO;AAErE,QAAIW,IAAS,IADCV,EAAS,QAAQ,cAAcA,EAAS,OAAO,QAAQ,EAC/C;AACtB,UAAMW,IAAQZ,EAAM,MAAM,GAAG,GACvBa,IAAa,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAC1C,WAAAD,EAAM,QAAQ,CAACE,GAAMC,MAAU;AAC7B,YAAMC,IAAYH,EAAWE,IAAQF,EAAW,MAAM;AACtD,UAAIX,GAAiB;AACnB,cAAM,CAACe,GAAQC,CAAQ,IAAIrB,EAAcmB,CAAS;AAClD,QAAAL,KAAU,QAAQM,CAAM,SAASC,CAAQ,IAAIJ,CAAI;AAAA,MACnD;AACE,QAAAH,KAAU,QAAQK,CAAS,IAAIF,CAAI;AAAA,IAEvC,CAAC,GACMH,EAAO,KAAA;AAAA,EAChB;AAGA,MAAIZ,MAAQ,YAAYE,EAAS,OAAOF,CAAG,MAAM,gBAAgBC,GAAO;AACtE,UAAMS,IAAQR,EAAS,QAAQ,cAAcA,EAAS,OAAO,SAAS;AACtE,WAAO,GAAGK,CAAK,GAAGG,CAAK,GAAGT,CAAK,GAAGQ,CAAM;AAAA,EAC1C;AAEA,SAAO,GAAGF,CAAK,GAAGG,CAAK,GAAGT,CAAK,GAAGQ,CAAM;AAC1C;AAgBA,SAASW,EAAaC,GAAcC,GAA6B;AAC/D,MAAIA,KAAa,EAAG,QAAOD,IAAO,CAACA,CAAI,IAAI,CAAA;AAE3C,QAAME,IAAkB,CAAA;AACxB,MAAIC,IAAc,IACdC,IAAe,GACfC,IAAa;AAEjB,WAASC,IAAI,GAAGA,IAAIN,EAAK,QAAQM,KAAK;AACpC,UAAMC,IAAOP,EAAKM,CAAC;AAGnB,QAAIC,MAAS,UAAUP,EAAKM,IAAI,CAAC,MAAM,KAAK;AAC1C,UAAIE,IAAMD,GACNE,IAAIH,IAAI;AACZ,aAAOG,IAAIT,EAAK,UAAUA,EAAKS,CAAC,MAAM;AACpC,QAAAD,KAAOR,EAAKS,CAAC,GACbA;AAEF,MAAIA,IAAIT,EAAK,WAAQQ,KAAOR,EAAKS,CAAC,IAClCN,KAAeK,GAEfH,IAAa,WAAW,KAAKG,CAAG,IAAI,KAAKA,GACzCF,IAAIG;AACJ;AAAA,IACF;AAGA,QAAIC,IAAOH,GACPI,IAAQ;AACZ,UAAMC,IAAOZ,EAAK,WAAWM,CAAC;AAC9B,IAAIM,KAAQ,SAAUA,KAAQ,SAAUN,IAAI,IAAIN,EAAK,WACnDU,IAAOH,IAAOP,EAAKM,IAAI,CAAC,GACxBK,IAAQ,GACRL,MAIEF,KAAgBH,MAClBC,EAAM,KAAKC,CAAW,GACtBA,IAAcE,GACdD,IAAe,IAGjBD,KAAeO,GACfN,KAAgBO;AAAA,EAClB;AAEA,SAAIR,KAAaD,EAAM,KAAKC,CAAW,GAEhCD;AACT;AAEA,eAAeW,EACbC,IAAwC,MACzB;AACf,QAAMjC,IAAWkC,EAAA,GACXC,IAAeF,KAAsBjC,EAAS,eAG9CoC,IAAO,MAAMC,EAAA;AAGnB,MAAIrC,EAAS,QAAQ,aAAa;AAChC,UAAMsC,IAAqB,CAAA;AAE3B,eAAWC,KAASJ;AAClB,iBAAWrC,KAAOyC,GAAO;AACvB,cAAMxC,IAAQqC,EAAKtC,CAAuB,GACpC0C,IAAY3C,EAAYC,GAAKC,GAAOC,CAAQ;AAClD,QAAIwC,KAAaA,EAAU,UACzBF,EAAS,KAAKE,CAAS;AAAA,MAE3B;AAGF,IAAIF,EAAS,SAAS,KACpB,QAAQ,IAAIA,EAAS,KAAK,GAAG,IAAIhC,EAAO,KAAK;AAE/C;AAAA,EACF;AAIA,QAAMmC,IAAgBzC,EAAS,QAAQ,kBACjCsC,IAAqB,CAAA;AAE3B,aAAWC,KAASJ;AAClB,eAAWrC,KAAOyC,GAAO;AACvB,YAAMxC,IAAQqC,EAAKtC,CAAuB,GACpC0C,IAAY3C,EAAYC,GAAKC,GAAOC,CAAQ;AAElD,MAAIwC,KAAaA,EAAU,UACzBF,EAAS,KAAKE,CAAS;AAAA,IAE3B;AAGF,QAAMnB,IAAQH,EAAaoB,EAAS,KAAK,GAAG,GAAGG,CAAa;AAG5D,EAAIpB,EAAM,SAAS,IACjBA,EAAM,QAAQ,CAACqB,MAAS;AACtB,YAAQ,IAAIA,IAAOpC,EAAO,KAAK;AAAA,EACjC,CAAC,IACQN,EAAS,SAAS,SAC3B,QAAQ,IAAI,0CAA0C;AAE1D;AAEA,SAAS2C,EAAsBC,GAAyB;AACtD,QAAM5C,IAAWkC,EAAA;AAEjB,MAAIU,EAAK,SAAS,iBAAiB;AACjC,WAAIC,EAAaC,CAAgB,IAC/B,QAAQ,IAAI,oCAAoC,IAEhD,QAAQ,IAAI,+BAA+B,GAEtC;AAGT,MAAIF,EAAK,SAAS,iBAAiB;AACjC,mBAAQ,IAAI,mBAAmB,GAC/B,QAAQ,IAAI,KAAK,UAAU5C,GAAU,MAAM,CAAC,CAAC,GACtC;AAGT,MAAI4C,EAAK,SAAS,kBAAkB;AAClC,WAAIC,EAAaC,CAAgB,IAC/B,QAAQ,IAAI,4BAA4B,IAExC,QAAQ,IAAI,0BAA0B,GAEjC;AAGT,MAAIF,EAAK,SAAS,WAAW,GAAG;AAC9B,QAAI;AACF,MAAIG,EAAG,WAAWC,CAAU,MAC1BD,EAAG,WAAWC,CAAU,GACxB,QAAQ,IAAI,eAAe;AAAA,IAE/B,SAASC,GAAO;AACd,cAAQ,MAAM,yBAA0BA,EAAgB,OAAO;AAAA,IACjE;AACA,WAAO;AAAA,EACT;AAEA,QAAMC,IAAWN,EAAK,QAAQ,OAAO;AACrC,MAAIM,MAAa,MAAMN,EAAKM,IAAW,CAAC,KAAKN,EAAKM,IAAW,CAAC,GAAG;AAC/D,UAAMpD,IAAM8C,EAAKM,IAAW,CAAC,GACvBnD,IAAQ6C,EAAKM,IAAW,CAAC;AAE/B,QAAI;AACF,YAAMC,IACJpD,EAAM,WAAW,GAAG,KAAKA,EAAM,WAAW,GAAG,IACzC,KAAK,MAAMA,CAAK,IAChBA,MAAU,SACV,KACAA,MAAU,UACV,KACAA,GAEAqD,IAAOtD,EAAI,MAAM,GAAG;AAC1B,UAAIuD,IAAerD;AACnB,eAASyB,IAAI,GAAGA,IAAI2B,EAAK,SAAS,GAAG3B;AACnC,QAAK4B,EAAQD,EAAK3B,CAAC,CAAC,MAAG4B,EAAQD,EAAK3B,CAAC,CAAC,IAAI,CAAA,IAC1C4B,IAAUA,EAAQD,EAAK3B,CAAC,CAAC;AAE3B,MAAA4B,EAAQD,EAAKA,EAAK,SAAS,CAAC,CAAC,IAAID,GAE7BN,EAAa7C,CAAQ,IACvB,QAAQ,IAAI,WAAWF,CAAG,MAAMC,CAAK,EAAE,IAEvC,QAAQ,IAAI,yBAAyB;AAAA,IAEzC,SAASkD,GAAO;AACd,cAAQ,MAAM,wBAAyBA,EAAgB,OAAO;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAASK,IAA6B;AACpC,QAAMC,IAAU5D,EAAG,QAAA;AAEnB,MAAI6D,GAAmBC;AACvB,EAAI/D,KACF8D,IAAYE,EAAK,KAAKH,GAAS,WAAW,OAAO,GACjDE,IAAaC,EAAK,KAAKF,GAAW,YAAY,MAE9CA,IAAYE,EAAK,KAAKH,GAAS,SAAS,GACxCE,IAAaC,EAAK,KAAKF,GAAW,YAAY;AAGhD,QAAMG,IAAgBD,EAAK,QAAQlE,CAAU;AAE7C,MAAI;AAUF,QATKuD,EAAG,WAAWS,CAAS,KAC1BT,EAAG,UAAUS,GAAW,EAAE,WAAW,IAAM,GAG7CT,EAAG,aAAaY,GAAeF,CAAU,GACpC/D,KACHqD,EAAG,UAAUU,GAAY,KAAK,GAG5B/D,GAAY;AACd,cAAQ,IAAI,uBAAuB,GACnC,QAAQ,IAAI,wBAAwB+D,CAAU,GAC9C,QAAQ,IAAI,uCAAuC,GACnD,QAAQ,IAAI,kCAAkCA,CAAU,IAAI,GAC5D,QAAQ;AAAA,QACN;AAAA,MAAA;AAGF,YAAMG,IAAaF,EAAK,KAAKF,GAAW,wBAAwB;AAChE,MAAAT,EAAG,cAAca,GAAY;AAAA,QAAoBH,CAAU;AAAA,CAAK,GAChE,QAAQ,IAAI,0BAA0BG,CAAU;AAAA,IAClD,OAAO;AACL,UAAI;AACF,cAAMC,IAAgBH,EAAK,KAAKH,GAAS,YAAY;AACrD,QAAAR,EAAG,cAAcc,GAAe,EAAE;AAAA,MACpC,QAAQ;AAAA,MAAC;AAET,YAAMC,IAAaJ,EAAK,KAAKH,GAAS,SAAS,GACzCQ,IAAW,QAAQN,CAAU;AAEnC,MAAIV,EAAG,WAAWe,CAAU,IACXf,EAAG,aAAae,GAAY,MAAM,EACrC,SAAS,YAAY,KAC/Bf,EAAG,eAAee,GAAY;AAAA,EAAKC,CAAQ;AAAA,CAAI,IAGjDhB,EAAG,cAAce,GAAY,GAAGC,CAAQ;AAAA,CAAI;AAG9C,YAAMC,IAAYN,EAAK,KAAKH,GAAS,QAAQ;AAC7C,MAAIR,EAAG,WAAWiB,CAAS,MACXjB,EAAG,aAAaiB,GAAW,MAAM,EACpC,SAAS,YAAY,KAC9BjB,EAAG,eAAeiB,GAAW;AAAA,EAAKD,CAAQ;AAAA,CAAI;AAIlD,YAAME,IAAiBP,EAAK;AAAA,QAC1BH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEF,MAAIR,EAAG,WAAWkB,CAAc,MACXlB,EAAG,aAAakB,GAAgB,MAAM,EACzC,SAAS,YAAY,KACnClB,EAAG;AAAA,QACDkB;AAAA,QACA;AAAA;AAAA,EAA8BF,CAAQ;AAAA;AAAA,MAAA;AAK5C,YAAMG,IAAoBR,EAAK;AAAA,QAC7BH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEF,MAAIR,EAAG,WAAWmB,CAAiB,MACXnB,EAAG,aAAamB,GAAmB,MAAM,EAC5C,SAAS,YAAY,KACtCnB,EAAG;AAAA,QACDmB;AAAA,QACA;AAAA;AAAA,EAAsCH,CAAQ;AAAA;AAAA,MAAA;AAAA,IAItD;AAEA,YAAQ,IAAI,wCAAwC;AAAA,EACtD,SAASd,GAAO;AACd,YAAQ,MAAM,oCAAqCA,EAAgB,OAAO,GAC1E,QAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,SAASkB,EAAavB,GAAiC;AACrD,aAAWwB,KAAOxB;AAChB,QAAI,CAACwB,EAAI,WAAW,IAAI,KAAKA,EAAI,SAAS,GAAG;AAC3C,aAAOA,EACJ,MAAM,GAAG,EACT,IAAI,CAACC,MAASA,EAAK,KAAA,CAAM,EACzB,OAAO,CAACA,MAASA,EAAK,SAAS,CAAC;AAIvC,aAAWD,KAAOxB;AAChB,QAAI,CAACwB,EAAI,WAAW,IAAI,KAAK,CAACA,EAAI,SAAS,GAAG,KAAKA,EAAI,SAAS;AAC9D,aAAO,CAACA,EAAI,MAAM;AAItB,SAAO;AACT;AAEA,eAAeE,IAA0B;AACvC,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBA8BGC,CAAa;AAAA,cAChBvB,CAAU;AAAA;AAAA,YAGpBtD,IACI,YACAC,EAAG,SAAA,MAAe,WAClB,UACAA,EAAG,SAAA,MAAe,UAClB,UACA,SACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CASD;AACD;AAEA,eAAe6E,IAAsB;AACnC,QAAM5B,IAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,MAAID,EAAsBC,CAAI;AAC5B;AAGF,MAAIA,EAAK,SAAS,QAAQ,KAAKA,EAAK,SAAS,IAAI,GAAG;AAClD,UAAM0B,EAAA;AACN;AAAA,EACF;AAEA,MAAI1B,EAAK,SAAS,WAAW,GAAG;AAC9B,IAAAU,EAAA;AACA;AAAA,EACF;AAEA,MAAIV,EAAK,SAAS,QAAQ,GAAG;AAC3B,UAAMR,IAAO,MAAMC,EAAA;AACnB,YAAQ,IAAI,KAAK,UAAUD,GAAM,MAAM,CAAC,CAAC;AACzC;AAAA,EACF;AAEA,QAAMqC,IAAWN,EAAavB,CAAI;AAClC,MAAI6B,GAAU;AAEZ,UAAMzC,EADqB,CAACyC,CAAQ,CACM;AAC1C;AAAA,EACF;AAEA,QAAMzC,EAAA;AACR;AAEAwC,IAAO,MAAM,CAACvB,MAAU;AACtB,UAAQ,MAAM,UAAUA,EAAM,OAAO,GACrC,QAAQ,KAAK,CAAC;AAChB,CAAC;"}
1
+ {"version":3,"file":"about-system-cli.js","sources":["../src/web-server.ts","../src/about-system-cli.ts"],"sourcesContent":["/**\n * @fileoverview `about-system web` — serves the React dashboard and a JSON API.\n *\n * The dashboard is prebuilt into dist/web by `vite build --config web/vite.config.ts`\n * and served as static files; the only dynamic route is GET /api/info, which\n * returns the same object as `about-system --json`.\n */\n\nimport http from \"http\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { getSystemInfo } from \"./system-info-api\";\n\nexport interface WebServerOptions {\n port?: number;\n host?: string;\n /** Directory holding the built dashboard. Defaults to dist/web next to this file. */\n webRoot?: string;\n}\n\nexport const DEFAULT_WEB_PORT = 3777;\nexport const DEFAULT_WEB_HOST = \"127.0.0.1\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff2\": \"font/woff2\",\n};\n\nfunction defaultWebRoot(): string {\n return path.join(path.dirname(fileURLToPath(import.meta.url)), \"web\");\n}\n\n/**\n * Resolves a request path to a file inside webRoot, or null if it escapes the\n * root or does not exist. Unknown paths fall back to index.html (SPA routing).\n */\nexport function resolveStaticFile(webRoot: string, urlPath: string): string | null {\n let decoded: string;\n try {\n decoded = decodeURIComponent(urlPath.split(\"?\")[0]);\n } catch {\n return null;\n }\n const root = path.resolve(webRoot);\n const candidate = path.resolve(root, \".\" + path.posix.normalize(\"/\" + decoded));\n if (candidate !== root && !candidate.startsWith(root + path.sep)) return null;\n\n if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate;\n const index = path.join(root, \"index.html\");\n return fs.existsSync(index) ? index : null;\n}\n\nfunction send(res: http.ServerResponse, status: number, type: string, body: string | Buffer): void {\n res.writeHead(status, {\n \"Content-Type\": type,\n \"Cache-Control\": \"no-store\",\n \"X-Content-Type-Options\": \"nosniff\",\n });\n res.end(body);\n}\n\nexport function createWebServer(options: WebServerOptions = {}): http.Server {\n const webRoot = options.webRoot ?? defaultWebRoot();\n\n return http.createServer(async (req, res) => {\n const url = req.url ?? \"/\";\n\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n send(res, 405, \"text/plain; charset=utf-8\", \"Method Not Allowed\");\n return;\n }\n\n if (url === \"/api/info\" || url.startsWith(\"/api/info?\")) {\n try {\n const info = await getSystemInfo();\n send(res, 200, MIME_TYPES[\".json\"], JSON.stringify(info));\n } catch (error) {\n send(res, 500, MIME_TYPES[\".json\"], JSON.stringify({ error: (error as Error).message }));\n }\n return;\n }\n\n const file = resolveStaticFile(webRoot, url);\n if (!file) {\n send(\n res,\n 404,\n \"text/plain; charset=utf-8\",\n \"Dashboard not found. Build it with: npm run build:web\"\n );\n return;\n }\n const type = MIME_TYPES[path.extname(file)] ?? \"application/octet-stream\";\n send(res, 200, type, fs.readFileSync(file));\n });\n}\n\n/** Starts the dashboard server and resolves with the URL it is listening on. */\nexport function startWebServer(options: WebServerOptions = {}): Promise<{ server: http.Server; url: string }> {\n const port = options.port ?? DEFAULT_WEB_PORT;\n const host = options.host ?? DEFAULT_WEB_HOST;\n const server = createWebServer(options);\n\n return new Promise((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, host, () => {\n const address = server.address();\n const actualPort = typeof address === \"object\" && address ? address.port : port;\n const shownHost = host === \"0.0.0.0\" || host === \"::\" ? \"localhost\" : host;\n resolve({ server, url: `http://${shownHost}:${actualPort}` });\n });\n });\n}\n","#!/usr/bin/env node\nimport os from \"os\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { getSystemInfo } from \"./system-info-api\";\nimport type { SystemInfo, SystemInfoOptions } from \"./systeminfo-types\";\nimport { startWebServer, DEFAULT_WEB_PORT, DEFAULT_WEB_HOST } from \"./web-server\";\n\nconst __filename = fileURLToPath(import.meta.url);\n\nimport {\n Settings,\n DEFAULT_SETTINGS,\n colors,\n backgrounds,\n SETTINGS_FILE,\n CACHE_FILE,\n loadSettings,\n saveSettings,\n} from \"./info/settings\";\n\n// Platform detection\nconst IS_WINDOWS = os.platform() === \"win32\";\n\n// Foreground code -> [background code, contrasting text code] for the\n// legacy 8-color multicolor rotation (ports/pacman rainbow mode).\nconst MULTICOLOR_BG: Record<number, [number, number]> = {\n 31: [41, 97], // red\n 32: [42, 30], // green\n 33: [43, 30], // yellow\n 34: [44, 97], // blue\n 35: [45, 97], // magenta\n 36: [46, 30], // cyan\n};\n\nfunction formatValue(key: string, value: string, settings: Settings): string {\n if (!value || value.trim() === \"\") return \"\";\n\n const showBackgrounds = settings.display.show_backgrounds !== false;\n const colorName = settings.colors[key] as keyof typeof colors;\n const bg = backgrounds[colorName as keyof typeof backgrounds];\n const style = (showBackgrounds && bg) || colors[colorName] || colors.reset;\n const suffix = showBackgrounds ? colors.reset : \"\";\n const emoji = settings.display.show_emojis ? settings.emojis[key] || \"\" : \"\";\n\n // Special handling for battery emoji\n if (key === \"battery\" && settings.display.show_emojis) {\n const batteryEmoji = value.includes(\"+\")\n ? settings.emojis.battery_charging\n : settings.emojis.battery;\n return `${style}${batteryEmoji}${value}${suffix}`;\n }\n\n // Multicolor handling for ports\n if (key === \"ports\" && settings.colors[key] === \"multicolor\" && value) {\n const emoji = settings.display.show_emojis ? settings.emojis.ports : \"\";\n let output = ` ${emoji}`;\n const ports = value.split(\" \");\n const colorCodes = [31, 32, 33, 34, 35, 36];\n ports.forEach((port, index) => {\n const colorCode = colorCodes[index % colorCodes.length];\n if (showBackgrounds) {\n const [bgCode, textCode] = MULTICOLOR_BG[colorCode];\n output += `\\x1b[${bgCode}m\\x1b[${textCode}m${port}\\x1b[0m `;\n } else {\n output += `\\x1b[${colorCode}m${port}\\x1b[0m `;\n }\n });\n return output.trim();\n }\n\n // Multicolor handling for pacman\n if (key === \"pacman\" && settings.colors[key] === \"multicolor\" && value) {\n const emoji = settings.display.show_emojis ? settings.emojis.pacman : \"\";\n return `${style}${emoji}${value}${suffix}`;\n }\n\n return `${style}${emoji}${value}${suffix}`;\n}\n\n/**\n * Wraps text to a maximum visible width, filling each line completely with\n * characters before moving on. Unlike block-boundary wrapping, this breaks in\n * the middle of an info block when it doesn't fit, so no visible space is left\n * unused at the end of a line.\n *\n * ANSI color codes are copied verbatim and never counted toward the width, and\n * the active color is re-applied at the start of each wrapped line so colors\n * survive a mid-block break. Emoji surrogate pairs are kept intact.\n *\n * @param text - The text to wrap (may contain ANSI escape sequences)\n * @param maxLength - Maximum visible characters per line\n * @returns Array of wrapped lines\n */\nfunction wrapAnsiText(text: string, maxLength: number): string[] {\n if (maxLength <= 0) return text ? [text] : [];\n\n const lines: string[] = [];\n let currentLine = \"\";\n let visibleCount = 0;\n let activeAnsi = \"\";\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n\n // Copy ANSI escape sequences verbatim without counting them.\n if (char === \"\\x1b\" && text[i + 1] === \"[\") {\n let seq = char;\n let j = i + 1;\n while (j < text.length && text[j] !== \"m\") {\n seq += text[j];\n j++;\n }\n if (j < text.length) seq += text[j]; // include the trailing \"m\"\n currentLine += seq;\n // Track the active color so wrapped lines keep it; a reset clears it.\n activeAnsi = /\\x1b\\[0m/.test(seq) ? \"\" : seq;\n i = j;\n continue;\n }\n\n // Keep an emoji (surrogate pair) together and count it as width 2.\n let unit = char;\n let width = 1;\n const code = text.charCodeAt(i);\n if (code >= 0xd800 && code <= 0xdbff && i + 1 < text.length) {\n unit = char + text[i + 1];\n width = 2;\n i++;\n }\n\n // Line is full: break here, even in the middle of an info block.\n if (visibleCount >= maxLength) {\n lines.push(currentLine);\n currentLine = activeAnsi;\n visibleCount = 0;\n }\n\n currentLine += unit;\n visibleCount += width;\n }\n\n if (currentLine) lines.push(currentLine);\n\n return lines;\n}\n\nasync function displaySystemInfo(\n customDisplayOrder: string[][] | null = null\n): Promise<void> {\n const settings = loadSettings();\n const displayOrder = customDisplayOrder || settings.display_order;\n\n // Get system info\n const info = await getSystemInfo();\n\n // Single line mode\n if (settings.display.single_line) {\n const allItems: string[] = [];\n\n for (const group of displayOrder) {\n for (const key of group) {\n const value = info[key as keyof SystemInfo] as string;\n const formatted = formatValue(key, value, settings);\n if (formatted && formatted.trim()) {\n allItems.push(formatted);\n }\n }\n }\n\n if (allItems.length > 0) {\n console.log(allItems.join(\" \") + colors.reset);\n }\n return;\n }\n\n // Multi-line mode: fill each line completely with characters, wrapping in\n // the middle of an info block when it no longer fits.\n const maxLineLength = settings.display.line_wrap_length;\n const allItems: string[] = [];\n\n for (const group of displayOrder) {\n for (const key of group) {\n const value = info[key as keyof SystemInfo] as string;\n const formatted = formatValue(key, value, settings);\n\n if (formatted && formatted.trim()) {\n allItems.push(formatted);\n }\n }\n }\n\n const lines = wrapAnsiText(allItems.join(\" \"), maxLineLength);\n\n // Output\n if (lines.length > 0) {\n lines.forEach((line) => {\n console.log(line + colors.reset);\n });\n } else if (settings.advanced.debug) {\n console.log(\"No system information could be displayed\");\n }\n}\n\nfunction handleSettingsCommand(args: string[]): boolean {\n const settings = loadSettings();\n\n if (args.includes(\"--settings-init\")) {\n if (saveSettings(DEFAULT_SETTINGS)) {\n console.log(\"Settings initialized with defaults\");\n } else {\n console.log(\"Failed to initialize settings\");\n }\n return true;\n }\n\n if (args.includes(\"--settings-show\")) {\n console.log(\"Current settings:\");\n console.log(JSON.stringify(settings, null, 2));\n return true;\n }\n\n if (args.includes(\"--settings-reset\")) {\n if (saveSettings(DEFAULT_SETTINGS)) {\n console.log(\"Settings reset to defaults\");\n } else {\n console.log(\"Failed to reset settings\");\n }\n return true;\n }\n\n if (args.includes(\"--refresh\")) {\n try {\n if (fs.existsSync(CACHE_FILE)) {\n fs.unlinkSync(CACHE_FILE);\n console.log(\"Cache cleared\");\n }\n } catch (error) {\n console.error(\"Error clearing cache:\", (error as Error).message);\n }\n return true;\n }\n\n const setIndex = args.indexOf(\"--set\");\n if (setIndex !== -1 && args[setIndex + 1] && args[setIndex + 2]) {\n const key = args[setIndex + 1];\n const value = args[setIndex + 2];\n\n try {\n const parsedValue =\n value.startsWith(\"{\") || value.startsWith(\"[\")\n ? JSON.parse(value)\n : value === \"true\"\n ? true\n : value === \"false\"\n ? false\n : value;\n\n const keys = key.split(\".\");\n let current: any = settings;\n for (let i = 0; i < keys.length - 1; i++) {\n if (!current[keys[i]]) current[keys[i]] = {};\n current = current[keys[i]];\n }\n current[keys[keys.length - 1]] = parsedValue;\n\n if (saveSettings(settings)) {\n console.log(`Setting ${key} = ${value}`);\n } else {\n console.log(\"Failed to save settings\");\n }\n } catch (error) {\n console.error(\"Error setting value:\", (error as Error).message);\n }\n return true;\n }\n\n return false;\n}\n\nfunction installShellGreeting(): void {\n const homeDir = os.homedir();\n\n let configDir: string, scriptPath: string;\n if (IS_WINDOWS) {\n configDir = path.join(homeDir, \"AppData\", \"Local\");\n scriptPath = path.join(configDir, \"systeminfo\");\n } else {\n configDir = path.join(homeDir, \".config\");\n scriptPath = path.join(configDir, \"systeminfo\");\n }\n\n const currentScript = path.resolve(__filename);\n\n try {\n if (!fs.existsSync(configDir)) {\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n fs.copyFileSync(currentScript, scriptPath);\n if (!IS_WINDOWS) {\n fs.chmodSync(scriptPath, \"755\");\n }\n\n if (IS_WINDOWS) {\n console.log(\"Windows installation:\");\n console.log(\"1. Script copied to:\", scriptPath);\n console.log(\"2. To add to PowerShell profile, run:\");\n console.log(` Add-Content $PROFILE \"node '${scriptPath}'\"`);\n console.log(\n \"3. To add to Command Prompt, create a batch file in your startup folder\"\n );\n\n const startupBat = path.join(configDir, \"systeminfo-startup.bat\");\n fs.writeFileSync(startupBat, `@echo off\\nnode \"${scriptPath}\"\\n`);\n console.log(\"4. Batch file created:\", startupBat);\n } else {\n try {\n const hushLoginPath = path.join(homeDir, \".hushlogin\");\n fs.writeFileSync(hushLoginPath, \"\");\n } catch {}\n\n const bashrcPath = path.join(homeDir, \".bashrc\");\n const bashLine = `node ${scriptPath}`;\n\n if (fs.existsSync(bashrcPath)) {\n const bashrc = fs.readFileSync(bashrcPath, \"utf8\");\n if (!bashrc.includes(\"systeminfo\")) {\n fs.appendFileSync(bashrcPath, `\\n${bashLine}\\n`);\n }\n } else {\n fs.writeFileSync(bashrcPath, `${bashLine}\\n`);\n }\n\n const zshrcPath = path.join(homeDir, \".zshrc\");\n if (fs.existsSync(zshrcPath)) {\n const zshrc = fs.readFileSync(zshrcPath, \"utf8\");\n if (!zshrc.includes(\"systeminfo\")) {\n fs.appendFileSync(zshrcPath, `\\n${bashLine}\\n`);\n }\n }\n\n const fishConfigPath = path.join(\n homeDir,\n \".config\",\n \"fish\",\n \"config.fish\"\n );\n if (fs.existsSync(fishConfigPath)) {\n const fishConfig = fs.readFileSync(fishConfigPath, \"utf8\");\n if (!fishConfig.includes(\"systeminfo\")) {\n fs.appendFileSync(\n fishConfigPath,\n `\\nset -U fish_greeting \"\"\\n${bashLine}\\n`\n );\n }\n }\n\n const nushellConfigPath = path.join(\n homeDir,\n \".config\",\n \"nushell\",\n \"config.nu\"\n );\n if (fs.existsSync(nushellConfigPath)) {\n const nushellConfig = fs.readFileSync(nushellConfigPath, \"utf8\");\n if (!nushellConfig.includes(\"systeminfo\")) {\n fs.appendFileSync(\n nushellConfigPath,\n `\\n$env.config.show_banner = false\\n${bashLine}\\n`\n );\n }\n }\n }\n\n console.log(\"Shell greeting installation completed!\");\n } catch (error) {\n console.error(\"Error installing shell greeting:\", (error as Error).message);\n process.exit(1);\n }\n}\n\n/** Reads `--flag value` or `--flag=value` from args. */\nfunction flagValue(args: string[], flag: string): string | undefined {\n for (let i = 0; i < args.length; i++) {\n if (args[i] === flag) return args[i + 1];\n if (args[i].startsWith(flag + \"=\")) return args[i].slice(flag.length + 1);\n }\n return undefined;\n}\n\nasync function runWebServer(args: string[]): Promise<void> {\n const rawPort = flagValue(args, \"--port\") ?? process.env.PORT;\n const port = rawPort === undefined ? DEFAULT_WEB_PORT : Number(rawPort);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n throw new Error(`Invalid port: ${rawPort}`);\n }\n const host = flagValue(args, \"--host\") ?? DEFAULT_WEB_HOST;\n\n const { url } = await startWebServer({ port, host });\n console.log(`About System web UI running at ${url}`);\n if (host === DEFAULT_WEB_HOST) {\n console.log(\"Listening on localhost only. Use --host 0.0.0.0 to expose it on the network.\");\n } else {\n console.log(\"Warning: system details (public IP, ports, processes) are visible to anyone who can reach this port.\");\n }\n console.log(\"Press Ctrl+C to stop.\");\n}\n\nfunction parseCLIMode(args: string[]): string[] | null {\n for (const arg of args) {\n if (!arg.startsWith(\"--\") && arg.includes(\",\")) {\n return arg\n .split(\",\")\n .map((part) => part.trim())\n .filter((part) => part.length > 0);\n }\n }\n\n for (const arg of args) {\n if (!arg.startsWith(\"--\") && !arg.includes(\"=\") && arg.length > 0) {\n return [arg.trim()];\n }\n }\n\n return null;\n}\n\nasync function showHelp(): Promise<void> {\n console.log(`\nSystem Info Script - TypeScript Version\n\nUsage:\n about-system [options]\n about-system <part1,part2,...> # CLI mode: show specific parts only\n about-system web [--port N] [--host H] # Serve the web dashboard\n\nOptions:\n --help, -h Show this help message\n --install Install as shell greeting\n --settings-init Initialize settings file with defaults\n --settings-show Display current settings\n --settings-reset Reset settings to defaults\n --refresh Clear the cache file\n --set <key> <value> Set a configuration value (use dot notation)\n --json Output as JSON\n\nExamples:\n about-system # Show all info (default)\n about-system cpu,os # Show only CPU and OS info\n about-system user,hostname,ip # Show user, hostname, and IP\n about-system disk_used # Show only disk usage\n about-system --install\n about-system --set display.show_emojis false\n about-system --set display.show_backgrounds false\n about-system --set colors.user blue\n about-system --set emojis.cpu \"🚀 \"\n about-system --set labels.cpu \"Processor\"\n about-system --json\n about-system web # http://127.0.0.1:${DEFAULT_WEB_PORT}\n about-system web --port 8080 --host 0.0.0.0\n\nSettings file: ${SETTINGS_FILE}\nCache file: ${CACHE_FILE}\n\nPlatform: ${\n IS_WINDOWS\n ? \"Windows\"\n : os.platform() === \"darwin\"\n ? \"macOS\"\n : os.platform() === \"linux\"\n ? \"Linux\"\n : \"Unknown\"\n }\n\nAvailable display blocks:\n Basic: user, hostname, uptime, shell, os, kernel, device\n Resources: disk_used, ram_used, memory_available, swap_used, top_process\n Network: ip, iplocal, city, domain, isp, network_interfaces\n Hardware: cpu, gpu, temperature, battery, screen_resolution\n System: load_average, users_logged_in, mount_points, services_running\n Tools: pacman, ports, containers\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n if (handleSettingsCommand(args)) {\n return;\n }\n\n if (args.includes(\"--help\") || args.includes(\"-h\")) {\n await showHelp();\n return;\n }\n\n if (args.includes(\"--install\")) {\n installShellGreeting();\n return;\n }\n\n if (args[0] === \"web\" || args.includes(\"--web\")) {\n await runWebServer(args);\n return;\n }\n\n if (args.includes(\"--json\")) {\n const info = await getSystemInfo();\n console.log(JSON.stringify(info, null, 2));\n return;\n }\n\n const cliParts = parseCLIMode(args);\n if (cliParts) {\n const customDisplayOrder = [cliParts];\n await displaySystemInfo(customDisplayOrder);\n return;\n }\n\n await displaySystemInfo();\n}\n\nmain().catch((error) => {\n console.error(\"Error:\", error.message);\n process.exit(1);\n});\n\nexport { displaySystemInfo, installShellGreeting };\n"],"names":["DEFAULT_WEB_PORT","DEFAULT_WEB_HOST","MIME_TYPES","defaultWebRoot","path","fileURLToPath","resolveStaticFile","webRoot","urlPath","decoded","root","candidate","fs","index","send","res","status","type","body","createWebServer","options","http","req","url","info","getSystemInfo","error","file","startWebServer","port","host","server","resolve","reject","address","actualPort","__filename","IS_WINDOWS","os","MULTICOLOR_BG","formatValue","key","value","settings","showBackgrounds","colorName","bg","backgrounds","style","colors","suffix","emoji","batteryEmoji","output","ports","colorCodes","colorCode","bgCode","textCode","wrapAnsiText","text","maxLength","lines","currentLine","visibleCount","activeAnsi","char","seq","j","unit","width","code","displaySystemInfo","customDisplayOrder","loadSettings","displayOrder","allItems","group","formatted","maxLineLength","line","handleSettingsCommand","args","saveSettings","DEFAULT_SETTINGS","CACHE_FILE","setIndex","parsedValue","keys","current","i","installShellGreeting","homeDir","configDir","scriptPath","currentScript","startupBat","hushLoginPath","bashrcPath","bashLine","zshrcPath","fishConfigPath","nushellConfigPath","flagValue","flag","runWebServer","rawPort","parseCLIMode","arg","part","showHelp","SETTINGS_FILE","main","cliParts"],"mappings":"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"}