about-system 0.0.18 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Platform-related system information functions
3
+ * @module info/platform
4
+ */
5
+
6
+ import os from "os";
7
+ import fs from "fs";
8
+ import type { InfoContext } from "../types/internal-types";
9
+ import { IS_WINDOWS, IS_MAC, IS_LINUX } from "../utils/platform";
10
+ import { execCommand, commandExists } from "../utils/command";
11
+ import { getCachedValue, setCachedValue } from "../cache/cache";
12
+
13
+ /**
14
+ * Gets the current username
15
+ * @returns Current system username
16
+ */
17
+ export function user(): string {
18
+ return os.userInfo().username;
19
+ }
20
+
21
+ /**
22
+ * Gets the system hostname
23
+ * @returns Computer hostname/network name
24
+ */
25
+ export function hostname(): string {
26
+ return os.hostname();
27
+ }
28
+
29
+ /**
30
+ * Gets operating system name and version
31
+ * Platform-specific detection for Windows, macOS, and Linux
32
+ * @param context - Info context with cache
33
+ * @returns OS name and version string
34
+ * @example "Windows 11 Pro", "macOS Ventura 13.2.1", "Ubuntu 22.04.3 LTS"
35
+ */
36
+ export function os_info(context: InfoContext): string {
37
+ const cached = getCachedValue(context.cache, "os");
38
+ if (cached) return cached;
39
+
40
+ const platform = os.platform();
41
+ const release = os.release();
42
+ let osName = "";
43
+
44
+ if (IS_WINDOWS) {
45
+ try {
46
+ const version = execCommand("ver");
47
+ const match = version.match(/Microsoft Windows \[Version ([^\]]+)\]/);
48
+ osName = match ? `Windows ${match[1]}` : `Windows ${release}`;
49
+ } catch {
50
+ osName = `Windows ${release}`;
51
+ }
52
+ } else if (IS_MAC) {
53
+ osName = `macOS ${release}`;
54
+ } else if (IS_LINUX) {
55
+ try {
56
+ const osRelease = fs.readFileSync("/etc/os-release", "utf8");
57
+ const nameMatch = osRelease.match(/^NAME="([^"]+)"/m);
58
+ const versionMatch = osRelease.match(/^VERSION_ID="([^"]+)"/m);
59
+ osName = nameMatch ? nameMatch[1] : "Linux";
60
+ if (versionMatch) osName += ` ${versionMatch[1]}`;
61
+ } catch {
62
+ osName = `Linux ${release}`;
63
+ }
64
+ } else {
65
+ osName = `${platform} ${release}`;
66
+ }
67
+
68
+ setCachedValue(context.cache, "os", osName);
69
+ return osName;
70
+ }
71
+
72
+ /**
73
+ * Gets kernel version string
74
+ * Returns the operating system kernel version from os.release()
75
+ * @param context - Info context with cache
76
+ * @returns Kernel version string
77
+ * @example "5.15.0-56-generic", "6.11.11-valve12-1-neptune"
78
+ */
79
+ export function kernel(context: InfoContext): string {
80
+ const cached = getCachedValue(context.cache, "kernel");
81
+ if (cached) return cached;
82
+
83
+ const kernel = os.release();
84
+ setCachedValue(context.cache, "kernel", kernel);
85
+ return kernel;
86
+ }
87
+
88
+ /**
89
+ * Gets device or computer model name
90
+ * Uses WMI on Windows, DMI on Linux, getprop on Android
91
+ * @param context - Info context with cache
92
+ * @returns Device model name or empty string
93
+ * @example "Dell OptiPlex 7090", "MacBook Pro 16-inch", "Valve Steam Deck"
94
+ */
95
+ export function device(context: InfoContext): string {
96
+ const cached = getCachedValue(context.cache, "device");
97
+ if (cached !== null) return cached;
98
+
99
+ if (IS_WINDOWS) {
100
+ try {
101
+ const wmic = execCommand("wmic csproduct get name /format:list");
102
+ const nameMatch = wmic.match(/Name=(.+)/);
103
+ if (nameMatch) {
104
+ const device = nameMatch[1].trim();
105
+ if (device && device !== "") {
106
+ setCachedValue(context.cache, "device", device);
107
+ return device;
108
+ }
109
+ }
110
+ } catch {}
111
+
112
+ try {
113
+ const ps = execCommand(
114
+ 'powershell.exe -Command "Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Model"'
115
+ );
116
+ if (ps.trim()) {
117
+ const device = ps.trim();
118
+ setCachedValue(context.cache, "device", device);
119
+ return device;
120
+ }
121
+ } catch {}
122
+ } else if (IS_LINUX) {
123
+ try {
124
+ if (commandExists("getprop")) {
125
+ const device = execCommand("getprop ro.product.model");
126
+ if (device) {
127
+ setCachedValue(context.cache, "device", device);
128
+ return device;
129
+ }
130
+ }
131
+
132
+ const dmiPath = "/sys/devices/virtual/dmi/id/product_name";
133
+ if (fs.existsSync(dmiPath)) {
134
+ const device = fs.readFileSync(dmiPath, "utf8").trim();
135
+ if (device) {
136
+ setCachedValue(context.cache, "device", device);
137
+ return device;
138
+ }
139
+ }
140
+ } catch {}
141
+ }
142
+
143
+ setCachedValue(context.cache, "device", "");
144
+ return "";
145
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Process-related system information functions
3
+ * @module info/process
4
+ */
5
+
6
+ import os from "os";
7
+ import type { InfoContext } from "../types/internal-types";
8
+ import { IS_LINUX } from "../utils/platform";
9
+ import { execCommand } from "../utils/command";
10
+ import { getCachedValue, setCachedValue } from "../cache/cache";
11
+
12
+ /**
13
+ * Gets the highest CPU-consuming process
14
+ * Uses ps command to find top process by CPU usage (Linux only)
15
+ * @param context - Info context with cache
16
+ * @returns Process info as "percentage processname" or empty string
17
+ * @example "8% firefox", "15% chrome", "3% systemd"
18
+ */
19
+ export function top_process(context: InfoContext): string {
20
+ const cached = getCachedValue(context.cache, "top_process");
21
+ if (cached !== null) return cached;
22
+
23
+ if (IS_LINUX) {
24
+ try {
25
+ const ps = execCommand("ps -eo pcpu,comm --sort=-%cpu --no-headers");
26
+ const lines = ps.split("\n");
27
+ if (lines.length > 0) {
28
+ const topProcess = lines[0].trim().replace(/\s+/, " ").split(" ");
29
+ const cpu = topProcess[0].replace(/\.\d+/, "%");
30
+ const process = topProcess[1].split("/").pop();
31
+ const result = `${cpu}% ${process}`;
32
+ setCachedValue(context.cache, "top_process", result);
33
+ return result;
34
+ }
35
+ } catch {}
36
+ }
37
+
38
+ setCachedValue(context.cache, "top_process", "");
39
+ return "";
40
+ }
41
+
42
+ /**
43
+ * Gets system uptime since last boot
44
+ * @returns Uptime formatted as "Xd Yh Zm"
45
+ * @example "2d 14h 23m", "0d 3h 45m"
46
+ */
47
+ export function uptime(): string {
48
+ const uptimeSeconds = os.uptime();
49
+ const days = Math.floor(uptimeSeconds / 86400);
50
+ const hours = Math.floor((uptimeSeconds % 86400) / 3600);
51
+ const minutes = Math.floor((uptimeSeconds % 3600) / 60);
52
+ return `${days}d ${hours}h ${minutes}m`;
53
+ }
54
+
55
+ /**
56
+ * Gets number of logged in users
57
+ * Uses who command to count active user sessions (Linux only)
58
+ * @returns User count with "users" suffix or empty string
59
+ * @example "3 users", "1 users"
60
+ */
61
+ export function users_logged_in(): string {
62
+ if (!IS_LINUX) return "";
63
+
64
+ try {
65
+ const who = execCommand("who");
66
+ const users = who.split("\n").filter((line) => line.trim()).length;
67
+ if (users > 0) {
68
+ return `${users} users`;
69
+ }
70
+ } catch {}
71
+ return "";
72
+ }
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Settings configuration and management
3
+ * @module info/settings
4
+ */
5
+
6
+ import path from "path";
7
+ import os from "os";
8
+ import fs from "fs";
9
+ import process from "process";
10
+
11
+ // Settings file paths
12
+ export const SETTINGS_FILE = path.join(
13
+ os.homedir(),
14
+ ".config",
15
+ "systeminfo-settings.json"
16
+ );
17
+ export const CACHE_FILE = path.join(os.tmpdir(), "systeminfo-cache.json");
18
+
19
+ // Color codes
20
+ export const colors = {
21
+ reset: "\x1b[0m",
22
+ red: "\x1b[38;5;196m",
23
+ orange: "\x1b[38;5;208m",
24
+ yellow: "\x1b[38;5;226m",
25
+ green: "\x1b[38;5;46m",
26
+ blue: "\x1b[38;5;39m",
27
+ cyan: "\x1b[38;5;51m",
28
+ purple: "\x1b[38;5;171m",
29
+ magenta: "\x1b[38;5;213m",
30
+ gray: "\x1b[38;5;250m",
31
+ lightblue: "\x1b[38;5;220m",
32
+ };
33
+
34
+ // Default settings
35
+ export const DEFAULT_SETTINGS = {
36
+ display_order: [
37
+ ["user", "hostname", "os", "device", "kernel", "cpu", "gpu"],
38
+ [
39
+ "disk_used",
40
+ "ram_used",
41
+ "top_process",
42
+ "uptime",
43
+ "temperature",
44
+ "battery",
45
+ "load_average",
46
+ ],
47
+ ["ip", "iplocal", "city", "domain", "isp"],
48
+ ["shell", "pacman", "services_running", "containers"],
49
+ ],
50
+ colors: {
51
+ user: "red",
52
+ hostname: "orange",
53
+ disk_used: "purple",
54
+ ram_used: "yellow",
55
+ top_process: "magenta",
56
+ uptime: "cyan",
57
+ ip: "green",
58
+ iplocal: "yellow",
59
+ city: "green",
60
+ domain: "gray",
61
+ isp: "lightblue",
62
+ os: "gray",
63
+ cpu: "orange",
64
+ gpu: "yellow",
65
+ device: "yellow",
66
+ kernel: "green",
67
+ shell: "orange",
68
+ pacman: "multicolor",
69
+ ports: "multicolor",
70
+ containers: "green",
71
+ memory_available: "blue",
72
+ swap_used: "purple",
73
+ load_average: "red",
74
+ users_logged_in: "cyan",
75
+ network_interfaces: "yellow",
76
+ mount_points: "gray",
77
+ services_running: "green",
78
+ temperature: "red",
79
+ battery: "green",
80
+ screen_resolution: "blue",
81
+ },
82
+ emojis: {
83
+ user: "👤 ",
84
+ hostname: "🏠 ",
85
+ ip: "🌎 ",
86
+ iplocal: "🌐 ",
87
+ city: "📍 ",
88
+ domain: "🔗 ",
89
+ isp: "👮 ",
90
+ os: "⚡ ",
91
+ cpu: "📈 ",
92
+ gpu: "🎮 ",
93
+ device: "💻 ",
94
+ kernel: "🔧 ",
95
+ shell: "🐚 ",
96
+ pacman: "🚀 ",
97
+ disk_used: "📁 ",
98
+ ram_used: "💾 ",
99
+ top_process: "🔝 ",
100
+ uptime: "⏱️ ",
101
+ ports: "🔌 ",
102
+ containers: "📦 ",
103
+ memory_available: "🧠 ",
104
+ swap_used: "🔄 ",
105
+ load_average: "⚖️ ",
106
+ users_logged_in: "👥 ",
107
+ network_interfaces: "🌐 ",
108
+ mount_points: "📂 ",
109
+ services_running: "⚙️ ",
110
+ temperature: "🌡️ ",
111
+ battery_charging: "🔌 ",
112
+ battery: "🔋 ",
113
+ screen_resolution: "🖥️ ",
114
+ },
115
+ labels: {
116
+ user: "User",
117
+ hostname: "Host",
118
+ ip: "IP",
119
+ iplocal: "Local IP",
120
+ city: "City",
121
+ domain: "Domain",
122
+ isp: "ISP",
123
+ os: "OS",
124
+ cpu: "CPU",
125
+ gpu: "GPU",
126
+ device: "Device",
127
+ kernel: "Kernel",
128
+ shell: "Shell",
129
+ pacman: "Packages",
130
+ disk_used: "Disk",
131
+ ram_used: "RAM",
132
+ top_process: "Top",
133
+ uptime: "Uptime",
134
+ ports: "Ports",
135
+ containers: "Containers",
136
+ memory_available: "Memory",
137
+ swap_used: "Swap",
138
+ load_average: "Load",
139
+ users_logged_in: "Users",
140
+ network_interfaces: "Network",
141
+ mount_points: "Mounts",
142
+ services_running: "Services",
143
+ temperature: "Temp",
144
+ battery_charging: "Battery",
145
+ battery: "Battery",
146
+ screen_resolution: "Resolution",
147
+ },
148
+ display: {
149
+ show_emojis: true,
150
+ single_line: false,
151
+ line_wrap_length: process?.stdout?.columns || 100,
152
+ },
153
+ network: {
154
+ show_offline_message: true,
155
+ },
156
+ advanced: {
157
+ debug: false,
158
+ },
159
+ };
160
+
161
+ export interface Settings {
162
+ display_order: string[][];
163
+ colors: Record<string, string>;
164
+ emojis: Record<string, string>;
165
+ labels: Record<string, string>;
166
+ display: {
167
+ show_emojis: boolean;
168
+ single_line: boolean;
169
+ line_wrap_length: number;
170
+ };
171
+ network: {
172
+ show_offline_message: boolean;
173
+ };
174
+ advanced: {
175
+ debug: boolean;
176
+ };
177
+ }
178
+
179
+ /**
180
+ * Loads settings from the configuration file
181
+ * @returns Settings object (defaults merged with user settings)
182
+ */
183
+ export function loadSettings(): Settings {
184
+ try {
185
+ if (fs.existsSync(SETTINGS_FILE)) {
186
+ const settings = JSON.parse(fs.readFileSync(SETTINGS_FILE, "utf8"));
187
+ return { ...DEFAULT_SETTINGS, ...settings };
188
+ }
189
+ } catch {}
190
+ return DEFAULT_SETTINGS;
191
+ }
192
+
193
+ /**
194
+ * Saves settings to the configuration file
195
+ * @param settings - The settings object to save
196
+ * @returns True if successful, false otherwise
197
+ */
198
+ export function saveSettings(settings: Settings): boolean {
199
+ try {
200
+ const configDir = path.dirname(SETTINGS_FILE);
201
+ if (!fs.existsSync(configDir)) {
202
+ fs.mkdirSync(configDir, { recursive: true });
203
+ }
204
+ fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2));
205
+ return true;
206
+ } catch {
207
+ return false;
208
+ }
209
+ }
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Software and package-related system information functions
3
+ * @module info/software
4
+ */
5
+
6
+ import process from "process";
7
+ import type { InfoContext } from "../types/internal-types";
8
+ import { IS_LINUX } from "../utils/platform";
9
+ import { execCommand, commandExists } from "../utils/command";
10
+ import { getCachedValue, setCachedValue } from "../cache/cache";
11
+
12
+ /**
13
+ * Gets the current shell name
14
+ * Uses ps command to find parent process shell (Linux/Unix only)
15
+ * @returns Shell name or empty string on Windows
16
+ * @example "bash", "zsh", "fish", "nu"
17
+ */
18
+ export function shell(context: InfoContext): string {
19
+ const cached = getCachedValue(context.cache, "shell");
20
+ if (cached !== null) return cached;
21
+
22
+ if (IS_LINUX) {
23
+ try {
24
+ const ppid = process.ppid;
25
+ const shellName = execCommand(`ps -p ${ppid} -o comm=`).split("/").pop();
26
+ if (shellName) {
27
+ setCachedValue(context.cache, "shell", shellName);
28
+ return shellName;
29
+ }
30
+ } catch {}
31
+ }
32
+
33
+ setCachedValue(context.cache, "shell", "");
34
+ return "";
35
+ }
36
+
37
+ /**
38
+ * Gets available package managers and development tools
39
+ * Checks for package managers (apt, yum, npm, etc.) and editors (nvim, hx)
40
+ * @param context - Info context with cache
41
+ * @returns Space-separated list of available commands
42
+ * @example "apt npm docker nvim", "yay pacman bun hx"
43
+ */
44
+ export function packages(context: InfoContext): string {
45
+ const cached = getCachedValue(context.cache, "packages");
46
+ if (cached !== null) return cached;
47
+
48
+ const commands = [
49
+ "apt",
50
+ "npm",
51
+ "uv",
52
+ "docker",
53
+ "hx",
54
+ "nvim",
55
+ "bun",
56
+ "yay",
57
+ "pacman",
58
+ "yum",
59
+ "dnf",
60
+ "zypper",
61
+ "emerge",
62
+ "apk",
63
+ "snap",
64
+ "flatpak",
65
+ ];
66
+ const available = commands.filter((cmd) => commandExists(cmd));
67
+
68
+ const result = available.join(" ");
69
+ setCachedValue(context.cache, "packages", result);
70
+ return result;
71
+ }
72
+
73
+ /**
74
+ * Gets versions of common software tools
75
+ * @param context - Info context with cache
76
+ * @returns Formatted string of tool versions
77
+ * @example "node:20.1.0 git:2.34.1"
78
+ */
79
+ export function common_versions(context: InfoContext): string {
80
+ const cached = getCachedValue(context.cache, "common_versions");
81
+ if (cached !== null) return cached;
82
+
83
+ const tools = [
84
+ {
85
+ cmd: "node",
86
+ args: "--version",
87
+ clean: (v: string) => v.replace(/^v/, ""),
88
+ },
89
+ {
90
+ cmd: "git",
91
+ args: "--version",
92
+ clean: (v: string) => v.replace("git version ", ""),
93
+ },
94
+ {
95
+ cmd: "docker",
96
+ args: "--version",
97
+ clean: (v: string) => v.replace(/Docker version ([^,]+),.*/, "$1"),
98
+ },
99
+ {
100
+ cmd: "python3",
101
+ args: "--version",
102
+ clean: (v: string) => v.replace("Python ", ""),
103
+ },
104
+ {
105
+ cmd: "go",
106
+ args: "version",
107
+ clean: (v: string) => v.replace("go version go", "").split(" ")[0],
108
+ },
109
+ {
110
+ cmd: "rustc",
111
+ args: "--version",
112
+ clean: (v: string) => v.replace("rustc ", "").split(" ")[0],
113
+ },
114
+ ];
115
+
116
+ const versions: string[] = [];
117
+
118
+ for (const tool of tools) {
119
+ if (commandExists(tool.cmd)) {
120
+ try {
121
+ const output = execCommand(`${tool.cmd} ${tool.args}`);
122
+ const version = tool.clean(output).trim();
123
+ if (version) {
124
+ versions.push(`${tool.cmd}:${version}`);
125
+ }
126
+ } catch {}
127
+ }
128
+ }
129
+
130
+ const result = versions.join(" ");
131
+ setCachedValue(context.cache, "common_versions", result);
132
+ return result;
133
+ }
134
+ /**
135
+ * Gets running Docker container names
136
+ * Lists active Docker containers with their names
137
+ * @param context - Info context with cache
138
+ * @returns Space-separated container names or empty string
139
+ * @example "nginx redis postgres", "web-app db-server"
140
+ */
141
+ export function containers(context: InfoContext): string {
142
+ const cached = getCachedValue(context.cache, "containers");
143
+ if (cached !== null) return cached;
144
+
145
+ if (!commandExists("docker")) {
146
+ setCachedValue(context.cache, "containers", "");
147
+ return "";
148
+ }
149
+
150
+ try {
151
+ const containerCount = execCommand("docker ps -q")
152
+ .split("\n")
153
+ .filter((line) => line.trim()).length;
154
+ if (containerCount === 0) {
155
+ setCachedValue(context.cache, "containers", "");
156
+ return "";
157
+ }
158
+
159
+ const containers = execCommand(
160
+ 'docker ps --format "{{.Names}}\t{{.Ports}}"'
161
+ );
162
+ const lines = containers.split("\n").filter((line) => line.trim());
163
+
164
+ const containerInfo: string[] = [];
165
+
166
+ lines.forEach((line) => {
167
+ const [name, ports] = line.split("\t");
168
+ if (name) {
169
+ containerInfo.push(name);
170
+
171
+ if (ports) {
172
+ const portMatches = ports.match(/->(\d+(-\d+)?)\//g);
173
+ if (portMatches) {
174
+ const uniquePorts = [
175
+ ...new Set(
176
+ portMatches.map((p) => p.replace(/->\d+(-\d+)?\//, ""))
177
+ ),
178
+ ];
179
+ containerInfo.push(...uniquePorts);
180
+ }
181
+ }
182
+ }
183
+ });
184
+
185
+ const result = containerInfo.join(" ");
186
+ setCachedValue(context.cache, "containers", result);
187
+ return result;
188
+ } catch {}
189
+
190
+ setCachedValue(context.cache, "containers", "");
191
+ return "";
192
+ }