about-system 0.10.9 → 0.10.11
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 +3 -1
- package/dist/about-system-cli.js +69 -54
- package/dist/about-system-cli.js.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +1 -1
- package/dist/system-info-api-D85U-_0W.js +2473 -0
- package/dist/system-info-api-D85U-_0W.js.map +1 -0
- package/dist/system-info-api.d.ts +15 -25
- package/dist/system-info-api.js +4 -5
- package/dist/system-info-api.js.map +1 -1
- package/package.json +1 -1
- package/src/about-system-cli.ts +42 -3
- package/src/cache/cache-config.ts +3 -3
- package/src/info/network.ts +14 -47
- package/src/system-info-api.test.ts +106 -0
- package/src/system-info-api.ts +68 -94
- package/src/systeminfo-types.d.ts +6 -0
- package/src/utils/network.ts +142 -23
- package/src/utils/utils.test.ts +136 -60
- package/dist/system-info-api-NgTm8Gzo.js +0 -2428
- package/dist/system-info-api-NgTm8Gzo.js.map +0 -1
package/README.md
CHANGED
|
@@ -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**:
|
|
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:
|
package/dist/about-system-cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import w from "os";
|
|
3
3
|
import c from "fs";
|
|
4
4
|
import u from "path";
|
|
5
|
-
import { fileURLToPath as
|
|
6
|
-
import { g as
|
|
7
|
-
import
|
|
8
|
-
const
|
|
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-D85U-_0W.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(
|
|
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
|
|
41
|
+
function H(e = {}) {
|
|
42
42
|
const o = e.webRoot ?? D();
|
|
43
|
-
return
|
|
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,
|
|
51
|
+
const r = await T();
|
|
52
|
+
m(s, 200, b[".json"], JSON.stringify(r));
|
|
53
53
|
} catch (r) {
|
|
54
|
-
m(s, 500,
|
|
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 =
|
|
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
|
|
73
|
-
const o = e.port ??
|
|
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
|
|
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
|
|
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((
|
|
106
|
-
const
|
|
105
|
+
return d.forEach((C, W) => {
|
|
106
|
+
const v = p[W % p.length];
|
|
107
107
|
if (s) {
|
|
108
|
-
const [
|
|
109
|
-
h += `\x1B[${
|
|
108
|
+
const [N, k] = J[v];
|
|
109
|
+
h += `\x1B[${N}m\x1B[${k}m${C}\x1B[0m `;
|
|
110
110
|
} else
|
|
111
|
-
h += `\x1B[${
|
|
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
|
|
140
|
-
const o =
|
|
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 =
|
|
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 =
|
|
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
|
|
163
|
-
const o =
|
|
175
|
+
function V(e) {
|
|
176
|
+
const o = O();
|
|
164
177
|
if (e.includes("--settings-init"))
|
|
165
|
-
return
|
|
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
|
|
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,
|
|
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
|
|
195
|
-
const e =
|
|
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(
|
|
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
|
|
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
|
|
262
|
-
const 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 =
|
|
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
|
|
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
|
|
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:${
|
|
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: ${
|
|
326
|
+
Settings file: ${A}
|
|
312
327
|
Cache file: ${j}
|
|
313
328
|
|
|
314
|
-
Platform: ${y ? "Windows" :
|
|
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
|
|
340
|
+
async function Z() {
|
|
326
341
|
const e = process.argv.slice(2);
|
|
327
|
-
if (
|
|
342
|
+
if (V(e))
|
|
328
343
|
return;
|
|
329
344
|
if (e.includes("--help") || e.includes("-h")) {
|
|
330
|
-
await
|
|
345
|
+
await Q();
|
|
331
346
|
return;
|
|
332
347
|
}
|
|
333
348
|
if (e.includes("--install")) {
|
|
334
|
-
|
|
349
|
+
Y();
|
|
335
350
|
return;
|
|
336
351
|
}
|
|
337
352
|
if (e[0] === "web" || e.includes("--web")) {
|
|
338
|
-
await
|
|
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 =
|
|
361
|
+
const o = X(e);
|
|
347
362
|
if (o) {
|
|
348
|
-
await
|
|
363
|
+
await E([o]);
|
|
349
364
|
return;
|
|
350
365
|
}
|
|
351
|
-
await
|
|
366
|
+
await E();
|
|
352
367
|
}
|
|
353
|
-
|
|
368
|
+
Z().catch((e) => {
|
|
354
369
|
console.error("Error:", e.message), process.exit(1);
|
|
355
370
|
});
|
|
356
371
|
export {
|
|
357
|
-
|
|
358
|
-
|
|
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
|
@@ -9,23 +9,35 @@ import { SystemInfoOptions as SystemInfoOptions_2 } from './systeminfo-types';
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Cache storage structure
|
|
12
|
+
* @interface Cache
|
|
12
13
|
*/
|
|
13
14
|
declare interface Cache {
|
|
14
15
|
[key: string]: CacheEntry;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Cache management utilities
|
|
20
|
+
* @module cache
|
|
21
|
+
*/
|
|
17
22
|
/**
|
|
18
23
|
* Represents a cached value with timestamp
|
|
24
|
+
* @interface CacheEntry
|
|
19
25
|
*/
|
|
20
26
|
declare interface CacheEntry {
|
|
27
|
+
/** The cached value */
|
|
21
28
|
value: any;
|
|
29
|
+
/** Unix timestamp when the value was cached */
|
|
22
30
|
timestamp: number;
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
export { DisplaySystemInfoFunction }
|
|
26
34
|
|
|
27
35
|
/**
|
|
28
|
-
* Get
|
|
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.
|
|
29
41
|
*/
|
|
30
42
|
export declare function getSystemInfo(options?: SystemInfoOptions_2): Promise<SystemInfo_2>;
|
|
31
43
|
|
package/dist/index.js
CHANGED