about-system 0.10.10 → 0.10.12

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 (58) hide show
  1. package/README.md +5 -3
  2. package/dist/about-system-cli.js +69 -54
  3. package/dist/about-system-cli.js.map +1 -1
  4. package/dist/index.d.ts +64 -18
  5. package/dist/index.js +1 -1
  6. package/dist/system-info-api-7iy1ZV2o.js +2475 -0
  7. package/dist/system-info-api-7iy1ZV2o.js.map +1 -0
  8. package/dist/system-info-api.d.ts +432 -62
  9. package/dist/system-info-api.js +1 -1
  10. package/dist/web/assets/index--HOsj3jw.js +14 -0
  11. package/dist/web/assets/index-BU_blZyu.css +1 -0
  12. package/dist/web/index.html +13 -0
  13. package/package.json +1 -1
  14. package/src/about-system-cli.ts +42 -3
  15. package/src/cache/cache-config.ts +3 -3
  16. package/src/info/hardware.test.ts +27 -12
  17. package/src/info/hardware.ts +25 -22
  18. package/src/info/network.ts +14 -47
  19. package/src/system-info-api.test.ts +106 -0
  20. package/src/system-info-api.ts +67 -28
  21. package/src/systeminfo-types.d.ts +16 -10
  22. package/src/utils/network.ts +113 -94
  23. package/src/utils/utils.test.ts +84 -75
  24. package/dist/about-system-cli.d.ts.map +0 -1
  25. package/dist/cache/cache-config.d.ts +0 -62
  26. package/dist/cache/cache-config.d.ts.map +0 -1
  27. package/dist/cache/cache.d.ts +0 -53
  28. package/dist/cache/cache.d.ts.map +0 -1
  29. package/dist/index.d.ts.map +0 -1
  30. package/dist/info/hardware.d.ts +0 -76
  31. package/dist/info/hardware.d.ts.map +0 -1
  32. package/dist/info/memory.d.ts +0 -59
  33. package/dist/info/memory.d.ts.map +0 -1
  34. package/dist/info/network.d.ts +0 -54
  35. package/dist/info/network.d.ts.map +0 -1
  36. package/dist/info/platform.d.ts +0 -36
  37. package/dist/info/platform.d.ts.map +0 -1
  38. package/dist/info/process.d.ts +0 -23
  39. package/dist/info/process.d.ts.map +0 -1
  40. package/dist/info/settings.d.ts +0 -185
  41. package/dist/info/settings.d.ts.map +0 -1
  42. package/dist/info/software.d.ts +0 -33
  43. package/dist/info/software.d.ts.map +0 -1
  44. package/dist/info/system-status.d.ts +0 -36
  45. package/dist/info/system-status.d.ts.map +0 -1
  46. package/dist/system-info-api-ByXoHI0m.js +0 -2464
  47. package/dist/system-info-api-ByXoHI0m.js.map +0 -1
  48. package/dist/system-info-api.d.ts.map +0 -1
  49. package/dist/types/internal-types.d.ts +0 -14
  50. package/dist/types/internal-types.d.ts.map +0 -1
  51. package/dist/utils/command.d.ts +0 -18
  52. package/dist/utils/command.d.ts.map +0 -1
  53. package/dist/utils/network.d.ts +0 -27
  54. package/dist/utils/network.d.ts.map +0 -1
  55. package/dist/utils/platform.d.ts +0 -11
  56. package/dist/utils/platform.d.ts.map +0 -1
  57. package/dist/web-server.d.ts +0 -21
  58. package/dist/web-server.d.ts.map +0 -1
package/README.md CHANGED
@@ -202,9 +202,9 @@ async function getBasicInfo() {
202
202
  | `isp` | Internet service provider | `👮 Verizon Business` |
203
203
  | `os` | Operating system | `⚡ Ubuntu 22.04` |
204
204
  | `cpu` | CPU information | `📈 Intel Core i7-8700K` |
205
- | `bench` | CPU Geekbench 6 multi-core, rank, top percentile | `💪 7k #612 top 62%` |
205
+ | `bench` | CPU Geekbench 6 multi-core, rank, top percentile | `💪 7k #612 Top 62%` |
206
206
  | `gpu` | Graphics card | `🎮 NVIDIA GeForce RTX 3080` |
207
- | `gpu_bench` | GPU Geekbench 6 OpenCL, rank, top percentile | `🏎️ 175k #140 top 14%` |
207
+ | `gpu_bench` | GPU Geekbench 6 OpenCL, rank, top percentile | `🏎️ 175k #140 Top 14%` |
208
208
  | `disk_used` | Disk usage percentage | `📁 75%` |
209
209
  | `disk_size` | Disk size per real disk | `💽 256/512GB` |
210
210
  | `ram_used` | Memory usage | `💾 8/16GB` |
@@ -389,11 +389,13 @@ about-system --set display.line_wrap_length 100
389
389
 
390
390
  The script implements intelligent caching to improve performance:
391
391
 
392
- - **IP Info**: 5 minutes (network requests are expensive)
392
+ - **IP Info**: 10 minutes, fetched with a 3-second deadline in parallel with local checks
393
393
  - **System Info**: 24 hours (rarely changes)
394
394
  - **Process Info**: 5 seconds (changes frequently)
395
395
  - **Disk/RAM**: 1 minute (moderate change frequency)
396
396
 
397
+ Press **Esc** at any point while it runs to stop and print only what has been collected so far.
398
+
397
399
  ### Shell Integration
398
400
 
399
401
  The `--install` flag automatically configures the script as a shell greeting:
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import S from "os";
2
+ import w from "os";
3
3
  import c from "fs";
4
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-ByXoHI0m.js";
7
- import A from "http";
8
- const C = 3777, _ = "127.0.0.1", w = {
5
+ import { fileURLToPath as P } from "url";
6
+ import { g as T, a as O, b as S, C as j, S as A, c as g, d as B, D as x } from "./system-info-api-7iy1ZV2o.js";
7
+ import R from "http";
8
+ const $ = 3777, _ = "127.0.0.1", b = {
9
9
  ".html": "text/html; charset=utf-8",
10
10
  ".js": "text/javascript; charset=utf-8",
11
11
  ".css": "text/css; charset=utf-8",
@@ -16,7 +16,7 @@ const C = 3777, _ = "127.0.0.1", w = {
16
16
  ".woff2": "font/woff2"
17
17
  };
18
18
  function D() {
19
- return u.join(u.dirname(O(import.meta.url)), "web");
19
+ return u.join(u.dirname(P(import.meta.url)), "web");
20
20
  }
21
21
  function U(e, o) {
22
22
  let t;
@@ -38,9 +38,9 @@ function m(e, o, t, s) {
38
38
  "X-Content-Type-Options": "nosniff"
39
39
  }), e.end(s);
40
40
  }
41
- function R(e = {}) {
41
+ function H(e = {}) {
42
42
  const o = e.webRoot ?? D();
43
- return A.createServer(async (t, s) => {
43
+ return R.createServer(async (t, s) => {
44
44
  const n = t.url ?? "/";
45
45
  if (t.method !== "GET" && t.method !== "HEAD") {
46
46
  m(s, 405, "text/plain; charset=utf-8", "Method Not Allowed");
@@ -48,10 +48,10 @@ function R(e = {}) {
48
48
  }
49
49
  if (n === "/api/info" || n.startsWith("/api/info?")) {
50
50
  try {
51
- const r = await $();
52
- m(s, 200, w[".json"], JSON.stringify(r));
51
+ const r = await T();
52
+ m(s, 200, b[".json"], JSON.stringify(r));
53
53
  } catch (r) {
54
- m(s, 500, w[".json"], JSON.stringify({ error: r.message }));
54
+ m(s, 500, b[".json"], JSON.stringify({ error: r.message }));
55
55
  }
56
56
  return;
57
57
  }
@@ -65,12 +65,12 @@ function R(e = {}) {
65
65
  );
66
66
  return;
67
67
  }
68
- const i = w[u.extname(l)] ?? "application/octet-stream";
68
+ const i = b[u.extname(l)] ?? "application/octet-stream";
69
69
  m(s, 200, i, c.readFileSync(l));
70
70
  });
71
71
  }
72
- function H(e = {}) {
73
- const o = e.port ?? C, t = e.host ?? _, s = R(e);
72
+ function z(e = {}) {
73
+ const o = e.port ?? $, t = e.host ?? _, s = H(e);
74
74
  return new Promise((n, l) => {
75
75
  s.once("error", l), s.listen(o, t, () => {
76
76
  const i = s.address(), r = typeof i == "object" && i ? i.port : o;
@@ -78,7 +78,7 @@ function H(e = {}) {
78
78
  });
79
79
  });
80
80
  }
81
- const z = O(import.meta.url), y = S.platform() === "win32", J = {
81
+ const M = P(import.meta.url), y = w.platform() === "win32", J = {
82
82
  31: [41, 97],
83
83
  // red
84
84
  32: [42, 30],
@@ -92,7 +92,7 @@ const z = O(import.meta.url), y = S.platform() === "win32", J = {
92
92
  36: [46, 30]
93
93
  // cyan
94
94
  };
95
- function E(e, o, t) {
95
+ function I(e, o, t) {
96
96
  if (!o || o.trim() === "") return "";
97
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
98
  if (e === "battery" && t.display.show_emojis) {
@@ -102,13 +102,13 @@ function E(e, o, t) {
102
102
  if (e === "ports" && t.colors[e] === "multicolor" && o) {
103
103
  let h = ` ${t.display.show_emojis ? t.emojis.ports : ""}`;
104
104
  const d = o.split(" "), p = [31, 32, 33, 34, 35, 36];
105
- return d.forEach((v, L) => {
106
- const x = p[L % p.length];
105
+ return d.forEach((C, W) => {
106
+ const v = p[W % p.length];
107
107
  if (s) {
108
- const [W, N] = J[x];
109
- h += `\x1B[${W}m\x1B[${N}m${v}\x1B[0m `;
108
+ const [N, k] = J[v];
109
+ h += `\x1B[${N}m\x1B[${k}m${C}\x1B[0m `;
110
110
  } else
111
- h += `\x1B[${x}m${v}\x1B[0m `;
111
+ h += `\x1B[${v}m${C}\x1B[0m `;
112
112
  }), h.trim();
113
113
  }
114
114
  if (e === "pacman" && t.colors[e] === "multicolor" && o) {
@@ -136,13 +136,26 @@ function G(e, o) {
136
136
  }
137
137
  return s && t.push(s), t;
138
138
  }
139
- async function F(e = null) {
140
- const o = T(), t = e || o.display_order, s = await $();
139
+ async function L(e) {
140
+ const o = new AbortController(), t = process.stdin, s = t.isTTY && typeof t.setRawMode == "function", n = () => {
141
+ t.off("data", l), t.setRawMode(!1), t.pause();
142
+ }, l = (i) => {
143
+ i.length === 1 && i[0] === 27 ? o.abort() : i.includes(3) && (n(), process.exit(130));
144
+ };
145
+ s && (t.setRawMode(!0), t.on("data", l), t.resume());
146
+ try {
147
+ return await T({ keys: e, signal: o.signal });
148
+ } finally {
149
+ s && n();
150
+ }
151
+ }
152
+ async function E(e = null) {
153
+ const o = O(), t = e || o.display_order, s = await L(t.flat());
141
154
  if (o.display.single_line) {
142
155
  const r = [];
143
156
  for (const a of t)
144
157
  for (const f of a) {
145
- const h = s[f], d = E(f, h, o);
158
+ const h = s[f], d = I(f, h, o);
146
159
  d && d.trim() && r.push(d);
147
160
  }
148
161
  r.length > 0 && console.log(r.join(" ") + g.reset);
@@ -151,7 +164,7 @@ async function F(e = null) {
151
164
  const n = o.display.line_wrap_length, l = [];
152
165
  for (const r of t)
153
166
  for (const a of r) {
154
- const f = s[a], h = E(a, f, o);
167
+ const f = s[a], h = I(a, f, o);
155
168
  h && h.trim() && l.push(h);
156
169
  }
157
170
  const i = G(l.join(" "), n);
@@ -159,14 +172,14 @@ async function F(e = null) {
159
172
  console.log(r + g.reset);
160
173
  }) : o.advanced.debug && console.log("No system information could be displayed");
161
174
  }
162
- function M(e) {
163
- const o = T();
175
+ function V(e) {
176
+ const o = O();
164
177
  if (e.includes("--settings-init"))
165
- return b(I) ? console.log("Settings initialized with defaults") : console.log("Failed to initialize settings"), !0;
178
+ return S(x) ? console.log("Settings initialized with defaults") : console.log("Failed to initialize settings"), !0;
166
179
  if (e.includes("--settings-show"))
167
180
  return console.log("Current settings:"), console.log(JSON.stringify(o, null, 2)), !0;
168
181
  if (e.includes("--settings-reset"))
169
- return b(I) ? console.log("Settings reset to defaults") : console.log("Failed to reset settings"), !0;
182
+ return S(x) ? console.log("Settings reset to defaults") : console.log("Failed to reset settings"), !0;
170
183
  if (e.includes("--refresh")) {
171
184
  try {
172
185
  c.existsSync(j) && (c.unlinkSync(j), console.log("Cache cleared"));
@@ -183,7 +196,7 @@ function M(e) {
183
196
  let r = o;
184
197
  for (let a = 0; a < i.length - 1; a++)
185
198
  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");
199
+ r[i[i.length - 1]] = l, S(o) ? console.log(`Setting ${s} = ${n}`) : console.log("Failed to save settings");
187
200
  } catch (l) {
188
201
  console.error("Error setting value:", l.message);
189
202
  }
@@ -191,11 +204,11 @@ function M(e) {
191
204
  }
192
205
  return !1;
193
206
  }
194
- function V() {
195
- const e = S.homedir();
207
+ function Y() {
208
+ const e = w.homedir();
196
209
  let o, t;
197
210
  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);
211
+ const s = u.resolve(M);
199
212
  try {
200
213
  if (c.existsSync(o) || c.mkdirSync(o, { recursive: !0 }), c.copyFileSync(s, t), y || c.chmodSync(t, "755"), y) {
201
214
  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(
@@ -252,20 +265,20 @@ ${l}
252
265
  console.error("Error installing shell greeting:", n.message), process.exit(1);
253
266
  }
254
267
  }
255
- function P(e, o) {
268
+ function F(e, o) {
256
269
  for (let t = 0; t < e.length; t++) {
257
270
  if (e[t] === o) return e[t + 1];
258
271
  if (e[t].startsWith(o + "=")) return e[t].slice(o.length + 1);
259
272
  }
260
273
  }
261
- async function X(e) {
262
- const o = P(e, "--port") ?? process.env.PORT, t = o === void 0 ? C : Number(o);
274
+ async function K(e) {
275
+ const o = F(e, "--port") ?? process.env.PORT, t = o === void 0 ? $ : Number(o);
263
276
  if (!Number.isInteger(t) || t < 0 || t > 65535)
264
277
  throw new Error(`Invalid port: ${o}`);
265
- const s = P(e, "--host") ?? _, { url: n } = await H({ port: t, host: s });
278
+ const s = F(e, "--host") ?? _, { url: n } = await z({ port: t, host: s });
266
279
  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
280
  }
268
- function Y(e) {
281
+ function X(e) {
269
282
  for (const o of e)
270
283
  if (!o.startsWith("--") && o.includes(","))
271
284
  return o.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
@@ -274,7 +287,7 @@ function Y(e) {
274
287
  return [o.trim()];
275
288
  return null;
276
289
  }
277
- async function K() {
290
+ async function Q() {
278
291
  console.log(`
279
292
  System Info Script - TypeScript Version
280
293
 
@@ -293,6 +306,8 @@ Options:
293
306
  --set <key> <value> Set a configuration value (use dot notation)
294
307
  --json Output as JSON
295
308
 
309
+ Press Esc while it runs to stop and print only what was collected so far.
310
+
296
311
  Examples:
297
312
  about-system # Show all info (default)
298
313
  about-system cpu,os # Show only CPU and OS info
@@ -305,13 +320,13 @@ Examples:
305
320
  about-system --set emojis.cpu "🚀 "
306
321
  about-system --set labels.cpu "Processor"
307
322
  about-system --json
308
- about-system web # http://127.0.0.1:${C}
323
+ about-system web # http://127.0.0.1:${$}
309
324
  about-system web --port 8080 --host 0.0.0.0
310
325
 
311
- Settings file: ${k}
326
+ Settings file: ${A}
312
327
  Cache file: ${j}
313
328
 
314
- Platform: ${y ? "Windows" : S.platform() === "darwin" ? "macOS" : S.platform() === "linux" ? "Linux" : "Unknown"}
329
+ Platform: ${y ? "Windows" : w.platform() === "darwin" ? "macOS" : w.platform() === "linux" ? "Linux" : "Unknown"}
315
330
 
316
331
  Available display blocks:
317
332
  Basic: user, hostname, uptime, shell, os, kernel, device
@@ -322,39 +337,39 @@ Available display blocks:
322
337
  Tools: pacman, ports, containers
323
338
  `);
324
339
  }
325
- async function Q() {
340
+ async function Z() {
326
341
  const e = process.argv.slice(2);
327
- if (M(e))
342
+ if (V(e))
328
343
  return;
329
344
  if (e.includes("--help") || e.includes("-h")) {
330
- await K();
345
+ await Q();
331
346
  return;
332
347
  }
333
348
  if (e.includes("--install")) {
334
- V();
349
+ Y();
335
350
  return;
336
351
  }
337
352
  if (e[0] === "web" || e.includes("--web")) {
338
- await X(e);
353
+ await K(e);
339
354
  return;
340
355
  }
341
356
  if (e.includes("--json")) {
342
- const t = await $();
357
+ const t = await L();
343
358
  console.log(JSON.stringify(t, null, 2));
344
359
  return;
345
360
  }
346
- const o = Y(e);
361
+ const o = X(e);
347
362
  if (o) {
348
- await F([o]);
363
+ await E([o]);
349
364
  return;
350
365
  }
351
- await F();
366
+ await E();
352
367
  }
353
- Q().catch((e) => {
368
+ Z().catch((e) => {
354
369
  console.error("Error:", e.message), process.exit(1);
355
370
  });
356
371
  export {
357
- F as displaySystemInfo,
358
- V as installShellGreeting
372
+ E as displaySystemInfo,
373
+ Y as installShellGreeting
359
374
  };
360
375
  //# sourceMappingURL=about-system-cli.js.map
@@ -1 +1 @@
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, bench, gpu, gpu_bench, 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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"}
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\n/**\n * Collects system info, stopping early when Esc is pressed. On Esc the blocks\n * gathered so far are returned and the rest are skipped. Only listens when\n * stdin is an interactive terminal; raw mode swallows Ctrl+C, so that is\n * handled here too.\n */\nasync function collectSystemInfo(keys?: string[]): Promise<SystemInfo> {\n const controller = new AbortController();\n const stdin = process.stdin;\n const listen = stdin.isTTY && typeof stdin.setRawMode === \"function\";\n\n const stopListening = () => {\n stdin.off(\"data\", onKey);\n stdin.setRawMode(false);\n stdin.pause();\n };\n const onKey = (data: Buffer) => {\n // A lone ESC byte; arrow keys etc. arrive as longer ESC sequences.\n if (data.length === 1 && data[0] === 0x1b) controller.abort();\n else if (data.includes(0x03)) {\n stopListening();\n process.exit(130);\n }\n };\n\n if (listen) {\n stdin.setRawMode(true);\n stdin.on(\"data\", onKey);\n stdin.resume();\n }\n try {\n return await getSystemInfo({ keys, signal: controller.signal });\n } finally {\n if (listen) stopListening();\n }\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 only the blocks that will be shown\n const info = await collectSystemInfo(displayOrder.flat());\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\nPress Esc while it runs to stop and print only what was collected so far.\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, bench, gpu, gpu_bench, 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 collectSystemInfo();\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","collectSystemInfo","keys","controller","stdin","listen","stopListening","onKey","data","displaySystemInfo","customDisplayOrder","loadSettings","displayOrder","allItems","group","formatted","maxLineLength","line","handleSettingsCommand","args","saveSettings","DEFAULT_SETTINGS","CACHE_FILE","setIndex","parsedValue","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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"}
package/dist/index.d.ts CHANGED
@@ -1,18 +1,64 @@
1
- /**
2
- * @fileoverview Main entry point for about-system package
3
- *
4
- * Exports the system information API for programmatic use.
5
- * For CLI usage, use the 'about-system' command directly.
6
- *
7
- * @example
8
- * ```typescript
9
- * import { getSystemInfo } from 'about-system';
10
- *
11
- * const info = await getSystemInfo();
12
- * console.log(info.cpu);
13
- * console.log(info.ram_used);
14
- * ```
15
- */
16
- export { getSystemInfo, loadCache, saveCache } from './system-info-api.js';
17
- export type { SystemInfo, SystemInfoOptions, Platform, GetSystemInfoFunction, DisplaySystemInfoFunction, PlatformAvailability } from './systeminfo-types.js';
18
- //# sourceMappingURL=index.d.ts.map
1
+ import { DisplaySystemInfoFunction } from './systeminfo-types.js';
2
+ import { GetSystemInfoFunction } from './systeminfo-types.js';
3
+ import { Platform } from './systeminfo-types.js';
4
+ import { PlatformAvailability } from './systeminfo-types.js';
5
+ import { SystemInfo } from './systeminfo-types.js';
6
+ import { SystemInfo as SystemInfo_2 } from './systeminfo-types';
7
+ import { SystemInfoOptions } from './systeminfo-types.js';
8
+ import { SystemInfoOptions as SystemInfoOptions_2 } from './systeminfo-types';
9
+
10
+ /**
11
+ * Cache storage structure
12
+ * @interface Cache
13
+ */
14
+ declare interface Cache {
15
+ [key: string]: CacheEntry;
16
+ }
17
+
18
+ /**
19
+ * Cache management utilities
20
+ * @module cache
21
+ */
22
+ /**
23
+ * Represents a cached value with timestamp
24
+ * @interface CacheEntry
25
+ */
26
+ declare interface CacheEntry {
27
+ /** The cached value */
28
+ value: any;
29
+ /** Unix timestamp when the value was cached */
30
+ timestamp: number;
31
+ }
32
+
33
+ export { DisplaySystemInfoFunction }
34
+
35
+ /**
36
+ * Get system information as a clean JSON object.
37
+ *
38
+ * `options.keys` limits collection to those blocks (all by default).
39
+ * `options.signal` stops collection early: whatever was gathered before the
40
+ * abort is returned, and the remaining blocks are left out.
41
+ */
42
+ export declare function getSystemInfo(options?: SystemInfoOptions_2): Promise<SystemInfo_2>;
43
+
44
+ export { GetSystemInfoFunction }
45
+
46
+ /**
47
+ * Loads cache from disk
48
+ */
49
+ export declare function loadCache(): Cache;
50
+
51
+ export { Platform }
52
+
53
+ export { PlatformAvailability }
54
+
55
+ /**
56
+ * Saves cache to disk
57
+ */
58
+ export declare function saveCache(cache: Cache): void;
59
+
60
+ export { SystemInfo }
61
+
62
+ export { SystemInfoOptions }
63
+
64
+ export { }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { g as s, l as o, s as t } from "./system-info-api-ByXoHI0m.js";
1
+ import { g as s, l as o, s as t } from "./system-info-api-7iy1ZV2o.js";
2
2
  export {
3
3
  s as getSystemInfo,
4
4
  o as loadCache,