about-system 0.0.4 → 0.0.8
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 +1 -1
- package/package.json +23 -11
- package/{about-system.js → src/about-system.js} +159 -25
- package/src/test-speed-cloudflare.js +51 -0
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ npx about-system
|
|
|
101
101
|
|
|
102
102
|
The script uses a JSON settings file located at:
|
|
103
103
|
- **Linux/macOS**: `~/.config/systeminfo-settings.json`
|
|
104
|
-
- **Windows**: `%APPDATA%\
|
|
104
|
+
- **Windows**: `%APPDATA%\systeminfo-settings.json`
|
|
105
105
|
|
|
106
106
|
#### Settings Commands
|
|
107
107
|
|
package/package.json
CHANGED
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "about-system",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "A Node.js script to display key system information with emojis. Cross-platform support for Windows, macOS, and Linux with customizable output and caching.",
|
|
5
|
-
"main": "about-system.js",
|
|
5
|
+
"main": "src/about-system.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"about-system": "./about-system.js"
|
|
7
|
+
"about-system": "./src/about-system.js",
|
|
8
|
+
"test-speed": "./src/test-speed-cloudflare.js"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./src/systeminfo-types.d.ts",
|
|
14
|
+
"import": "./src/about-system.js"
|
|
15
|
+
}
|
|
8
16
|
},
|
|
9
17
|
"scripts": {
|
|
10
18
|
"ship": "npx standard-version --release-as patch; npm publish",
|
|
11
|
-
"start": "node about-system.js",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
19
|
+
"start": "node src/about-system.js",
|
|
20
|
+
"test-speed": "node src/test-speed-cloudflare.js",
|
|
21
|
+
"install-greeting": "node src/about-system.js --install",
|
|
22
|
+
"show-settings": "node src/about-system.js --settings-show",
|
|
23
|
+
"reset-settings": "node src/about-system.js --settings-reset",
|
|
24
|
+
"clear-cache": "node src/about-system.js --cache-clear",
|
|
25
|
+
"help": "node src/about-system.js --help"
|
|
17
26
|
},
|
|
18
27
|
"keywords": [
|
|
19
|
-
"about-system",
|
|
28
|
+
"src/about-system",
|
|
20
29
|
"system",
|
|
21
30
|
"information",
|
|
22
31
|
"cli",
|
|
@@ -38,7 +47,7 @@
|
|
|
38
47
|
},
|
|
39
48
|
"homepage": "https://github.com/vtempest/server-shell-setup#readme",
|
|
40
49
|
"files": [
|
|
41
|
-
"about-system.js",
|
|
50
|
+
"src/about-system.js",
|
|
42
51
|
"README.md",
|
|
43
52
|
"package.json"
|
|
44
53
|
],
|
|
@@ -51,5 +60,8 @@
|
|
|
51
60
|
"preferGlobal": true,
|
|
52
61
|
"directories": {
|
|
53
62
|
"bin": "."
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"ora": "^8.2.0"
|
|
54
66
|
}
|
|
55
67
|
}
|
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
* Network info (ip, city, domain, isp) is fetched from ipinfo.io
|
|
16
16
|
* only if needed.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* License: MIT
|
|
18
|
+
* @author: vtempest
|
|
19
|
+
* @license: MIT
|
|
21
20
|
*/
|
|
22
21
|
|
|
23
22
|
const os = require('os');
|
|
@@ -106,17 +105,7 @@ const DEFAULT_SETTINGS = {
|
|
|
106
105
|
multiline: true,
|
|
107
106
|
group_similar: true,
|
|
108
107
|
single_line: false,
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
const { execSync } = require('child_process');
|
|
112
|
-
const size = execSync('stty size', { encoding: 'utf8' }).trim();
|
|
113
|
-
const cols = parseInt(size.split(' ')[1]);
|
|
114
|
-
console.log(cols)
|
|
115
|
-
return cols > 0 ? cols : 100; // fallback to 100 if stty fails
|
|
116
|
-
} catch (error) {
|
|
117
|
-
return 100; // fallback to 100 if stty is not available
|
|
118
|
-
}
|
|
119
|
-
})()
|
|
108
|
+
line_wrap_length: process?.stdout?.columns || 100, // fallback to 80 if tput fails
|
|
120
109
|
},
|
|
121
110
|
advanced: {
|
|
122
111
|
debug: false,
|
|
@@ -449,7 +438,26 @@ const infoFunctions = {
|
|
|
449
438
|
|
|
450
439
|
let cpuName = '';
|
|
451
440
|
|
|
452
|
-
if (
|
|
441
|
+
if (IS_WINDOWS) {
|
|
442
|
+
// Windows-specific CPU detection using WMIC
|
|
443
|
+
try {
|
|
444
|
+
const wmic = execCommand('wmic cpu get name /format:list');
|
|
445
|
+
const nameMatch = wmic.match(/Name=(.+)/);
|
|
446
|
+
if (nameMatch) {
|
|
447
|
+
cpuName = nameMatch[1].trim();
|
|
448
|
+
}
|
|
449
|
+
} catch {}
|
|
450
|
+
|
|
451
|
+
// Fallback to PowerShell if WMIC fails
|
|
452
|
+
if (!cpuName) {
|
|
453
|
+
try {
|
|
454
|
+
const ps = execCommand('powershell.exe -Command "Get-WmiObject -Class Win32_Processor | Select-Object -ExpandProperty Name"');
|
|
455
|
+
if (ps.trim()) {
|
|
456
|
+
cpuName = ps.trim();
|
|
457
|
+
}
|
|
458
|
+
} catch {}
|
|
459
|
+
}
|
|
460
|
+
} else if (IS_LINUX) {
|
|
453
461
|
// Try lscpu first (like bash script)
|
|
454
462
|
try {
|
|
455
463
|
const lscpu = execCommand('lscpu');
|
|
@@ -477,7 +485,7 @@ const infoFunctions = {
|
|
|
477
485
|
// Use Node.js os module for other platforms
|
|
478
486
|
const cpus = os.cpus();
|
|
479
487
|
if (cpus.length > 0) {
|
|
480
|
-
cpuName = cpus[0].model;
|
|
488
|
+
cpuName = cpus[0].model.trim().replace(/[\r\n]+/g, ' ');
|
|
481
489
|
}
|
|
482
490
|
}
|
|
483
491
|
|
|
@@ -487,7 +495,7 @@ const infoFunctions = {
|
|
|
487
495
|
}
|
|
488
496
|
|
|
489
497
|
//remove "with ..." from cpuName
|
|
490
|
-
cpuName = cpuName.replace(/with .*/, '');
|
|
498
|
+
cpuName = cpuName.trim().replace(/with .*/, '');
|
|
491
499
|
|
|
492
500
|
const color = colors[settings.colors.cpu] || colors.orange;
|
|
493
501
|
const emoji = settings.display.show_emojis ? '📈 ' : '';
|
|
@@ -500,7 +508,36 @@ const infoFunctions = {
|
|
|
500
508
|
const cached = getCachedValue(this.cache, 'gpu', settings);
|
|
501
509
|
if (cached) return cached;
|
|
502
510
|
|
|
503
|
-
if (
|
|
511
|
+
if (IS_WINDOWS) {
|
|
512
|
+
try {
|
|
513
|
+
// Get GPU information using WMIC
|
|
514
|
+
const wmic = execCommand('wmic path win32_VideoController get name /format:list');
|
|
515
|
+
const nameMatch = wmic.match(/Name=(.+)/);
|
|
516
|
+
if (nameMatch) {
|
|
517
|
+
const gpu = nameMatch[1].trim();
|
|
518
|
+
if (gpu && gpu !== '' && !gpu.includes('Microsoft Basic')) {
|
|
519
|
+
const color = colors[settings.colors.gpu] || colors.yellow;
|
|
520
|
+
const emoji = settings.display.show_emojis ? '🎮 ' : '';
|
|
521
|
+
const result = `${color}${emoji}${gpu}`;
|
|
522
|
+
setCachedValue(this.cache, 'gpu', result);
|
|
523
|
+
return result;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
} catch {}
|
|
527
|
+
|
|
528
|
+
// Fallback using PowerShell
|
|
529
|
+
try {
|
|
530
|
+
const ps = execCommand('powershell.exe -Command "Get-WmiObject -Class Win32_VideoController | Where-Object {$_.Name -notlike \'*Microsoft Basic*\'} | Select-Object -First 1 -ExpandProperty Name"');
|
|
531
|
+
if (ps.trim()) {
|
|
532
|
+
const gpu = ps.trim();
|
|
533
|
+
const color = colors[settings.colors.gpu] || colors.yellow;
|
|
534
|
+
const emoji = settings.display.show_emojis ? '🎮 ' : '';
|
|
535
|
+
const result = `${color}${emoji}${gpu}`;
|
|
536
|
+
setCachedValue(this.cache, 'gpu', result);
|
|
537
|
+
return result;
|
|
538
|
+
}
|
|
539
|
+
} catch {}
|
|
540
|
+
} else if (IS_LINUX) {
|
|
504
541
|
try {
|
|
505
542
|
const lspci = execCommand('lspci');
|
|
506
543
|
// Look for VGA and specific GPU brands like the bash script
|
|
@@ -536,7 +573,40 @@ const infoFunctions = {
|
|
|
536
573
|
const cached = getCachedValue(this.cache, 'disk_used', settings);
|
|
537
574
|
if (cached) return cached;
|
|
538
575
|
|
|
539
|
-
if (
|
|
576
|
+
if (IS_WINDOWS) {
|
|
577
|
+
try {
|
|
578
|
+
// Get disk usage for C: drive using PowerShell
|
|
579
|
+
const ps = execCommand('powershell.exe -Command "Get-WmiObject -Class Win32_LogicalDisk -Filter \'DeviceID="C:"\' | Select-Object @{Name=\'PercentFree\';Expression={[math]::Round((($_.FreeSpace / $_.Size) * 100), 0)}} | Select-Object -ExpandProperty PercentFree"');
|
|
580
|
+
if (ps.trim()) {
|
|
581
|
+
const percentFree = parseInt(ps.trim());
|
|
582
|
+
const percentUsed = 100 - percentFree;
|
|
583
|
+
const color = colors[settings.colors.disk_used] || colors.purple;
|
|
584
|
+
const emoji = settings.display.show_emojis ? '📁 ' : '';
|
|
585
|
+
const result = `${color}${emoji}${percentUsed}%`;
|
|
586
|
+
setCachedValue(this.cache, 'disk_used', result);
|
|
587
|
+
return result;
|
|
588
|
+
}
|
|
589
|
+
} catch {}
|
|
590
|
+
|
|
591
|
+
// Fallback using WMIC
|
|
592
|
+
try {
|
|
593
|
+
const wmic = execCommand('wmic logicaldisk where "DeviceID=\'C:\'" get Size,FreeSpace /format:list');
|
|
594
|
+
const sizeMatch = wmic.match(/Size=(\d+)/);
|
|
595
|
+
const freeMatch = wmic.match(/FreeSpace=(\d+)/);
|
|
596
|
+
|
|
597
|
+
if (sizeMatch && freeMatch) {
|
|
598
|
+
const size = parseInt(sizeMatch[1]);
|
|
599
|
+
const free = parseInt(freeMatch[1]);
|
|
600
|
+
const used = size - free;
|
|
601
|
+
const percentUsed = Math.round((used / size) * 100);
|
|
602
|
+
const color = colors[settings.colors.disk_used] || colors.purple;
|
|
603
|
+
const emoji = settings.display.show_emojis ? '📁 ' : '';
|
|
604
|
+
const result = `${color}${emoji}${percentUsed}%`;
|
|
605
|
+
setCachedValue(this.cache, 'disk_used', result);
|
|
606
|
+
return result;
|
|
607
|
+
}
|
|
608
|
+
} catch {}
|
|
609
|
+
} else if (IS_LINUX) {
|
|
540
610
|
try {
|
|
541
611
|
const df = execCommand('df -h');
|
|
542
612
|
let diskUsage = '';
|
|
@@ -628,7 +698,44 @@ const infoFunctions = {
|
|
|
628
698
|
const cached = getCachedValue(this.cache, 'top_process', settings);
|
|
629
699
|
if (cached) return cached;
|
|
630
700
|
|
|
631
|
-
if (
|
|
701
|
+
if (IS_WINDOWS) {
|
|
702
|
+
try {
|
|
703
|
+
// Get top process using PowerShell performance counters
|
|
704
|
+
const ps = execCommand('powershell.exe -Command "Get-Counter \'\\Process(*)\\% Processor Time\' | Select-Object -ExpandProperty CounterSamples | Where-Object {$_.InstanceName -notin @(\'_Total\', \'Idle\')} | Sort-Object CookedValue -Descending | Select-Object -First 1 | Select-Object InstanceName, @{Name=\'CPU%\'; Expression={[math]::Round($_.CookedValue, 1)}}"');
|
|
705
|
+
const lines = ps.split('\n').filter(line => line.trim());
|
|
706
|
+
if (lines.length > 0) {
|
|
707
|
+
const parts = lines[0].trim().split(/\s+/);
|
|
708
|
+
if (parts.length >= 2) {
|
|
709
|
+
const processName = parts[0];
|
|
710
|
+
const cpuPercent = parts[1];
|
|
711
|
+
const color = colors[settings.colors.top_process] || colors.magenta;
|
|
712
|
+
const emoji = settings.display.show_emojis ? '🔝 ' : '';
|
|
713
|
+
const result = `${color}${emoji}${cpuPercent}% ${processName}`;
|
|
714
|
+
setCachedValue(this.cache, 'top_process', result);
|
|
715
|
+
return result;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
} catch {}
|
|
719
|
+
|
|
720
|
+
// Fallback using tasklist
|
|
721
|
+
try {
|
|
722
|
+
const tasklist = execCommand('tasklist /fo csv | findstr /v "Image Name" | sort /r /+5');
|
|
723
|
+
const lines = tasklist.split('\n').filter(line => line.trim());
|
|
724
|
+
if (lines.length > 0) {
|
|
725
|
+
const line = lines[0];
|
|
726
|
+
const parts = line.split(',');
|
|
727
|
+
if (parts.length >= 5) {
|
|
728
|
+
const processName = parts[0].replace(/"/g, '').split('.')[0];
|
|
729
|
+
const memoryUsage = parts[4].replace(/"/g, '').replace(/[,\s]/g, '');
|
|
730
|
+
const color = colors[settings.colors.top_process] || colors.magenta;
|
|
731
|
+
const emoji = settings.display.show_emojis ? '🔝 ' : '';
|
|
732
|
+
const result = `${color}${emoji}${memoryUsage}KB ${processName}`;
|
|
733
|
+
setCachedValue(this.cache, 'top_process', result);
|
|
734
|
+
return result;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
} catch {}
|
|
738
|
+
} else if (IS_LINUX) {
|
|
632
739
|
try {
|
|
633
740
|
const ps = execCommand('ps -eo pcpu,comm --sort=-%cpu --no-headers');
|
|
634
741
|
const lines = ps.split('\n');
|
|
@@ -664,7 +771,36 @@ const infoFunctions = {
|
|
|
664
771
|
const cached = getCachedValue(this.cache, 'device', settings);
|
|
665
772
|
if (cached) return cached;
|
|
666
773
|
|
|
667
|
-
if (
|
|
774
|
+
if (IS_WINDOWS) {
|
|
775
|
+
try {
|
|
776
|
+
// Get computer model using WMIC
|
|
777
|
+
const wmic = execCommand('wmic csproduct get name /format:list');
|
|
778
|
+
const nameMatch = wmic.match(/Name=(.+)/);
|
|
779
|
+
if (nameMatch) {
|
|
780
|
+
const device = nameMatch[1].trim();
|
|
781
|
+
if (device && device !== '') {
|
|
782
|
+
const color = colors[settings.colors.device] || colors.blue;
|
|
783
|
+
const emoji = settings.display.show_emojis ? '💻 ' : '';
|
|
784
|
+
const result = `${color}${emoji}${device}`;
|
|
785
|
+
setCachedValue(this.cache, 'device', result);
|
|
786
|
+
return result;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
} catch {}
|
|
790
|
+
|
|
791
|
+
// Fallback using PowerShell
|
|
792
|
+
try {
|
|
793
|
+
const ps = execCommand('powershell.exe -Command "Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Model"');
|
|
794
|
+
if (ps.trim()) {
|
|
795
|
+
const device = ps.trim();
|
|
796
|
+
const color = colors[settings.colors.device] || colors.blue;
|
|
797
|
+
const emoji = settings.display.show_emojis ? '💻 ' : '';
|
|
798
|
+
const result = `${color}${emoji}${device}`;
|
|
799
|
+
setCachedValue(this.cache, 'device', result);
|
|
800
|
+
return result;
|
|
801
|
+
}
|
|
802
|
+
} catch {}
|
|
803
|
+
} else if (IS_LINUX) {
|
|
668
804
|
try {
|
|
669
805
|
// Check for Android
|
|
670
806
|
if (commandExists('getprop')) {
|
|
@@ -1250,17 +1386,15 @@ function handleSettingsCommand(args) {
|
|
|
1250
1386
|
return true;
|
|
1251
1387
|
}
|
|
1252
1388
|
|
|
1253
|
-
const cacheResetIndex = args.indexOf('--
|
|
1389
|
+
const cacheResetIndex = args.indexOf('--refresh');
|
|
1254
1390
|
if (cacheResetIndex !== -1) {
|
|
1255
1391
|
try {
|
|
1256
1392
|
if (fs.existsSync(CACHE_FILE)) {
|
|
1257
1393
|
fs.unlinkSync(CACHE_FILE);
|
|
1258
1394
|
}
|
|
1259
|
-
console.log('Cache cleared');
|
|
1260
1395
|
} catch (error) {
|
|
1261
1396
|
console.error('Error clearing cache:', error.message);
|
|
1262
1397
|
}
|
|
1263
|
-
return true;
|
|
1264
1398
|
}
|
|
1265
1399
|
|
|
1266
1400
|
const setIndex = args.indexOf('--set');
|
|
@@ -1440,7 +1574,7 @@ Options:
|
|
|
1440
1574
|
--settings-init Initialize settings file with defaults
|
|
1441
1575
|
--settings-show Display current settings
|
|
1442
1576
|
--settings-reset Reset settings to defaults
|
|
1443
|
-
--
|
|
1577
|
+
--refresh Clear the cache file
|
|
1444
1578
|
--set <key> <value> Set a configuration value (use dot notation)
|
|
1445
1579
|
|
|
1446
1580
|
Examples:
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
import { spawn, execSync } from 'child_process';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tests the download speed in MB/s using Cloudflare's speed test.
|
|
7
|
+
* Optionally displays a spinner message during the test.
|
|
8
|
+
* Their official package is @cloudflare/speedtest and it shows errors and too much output.
|
|
9
|
+
* This script uses a process to hide the errors and give speed in MB/s via CLI or import.
|
|
10
|
+
* @param {boolean} [showMessage=true] - Whether to show explanation message while testing.
|
|
11
|
+
* @returns {Promise<string>} The measured download speed in MB/s as a string (e.g., "12.3").
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* import { testDownloadSpeed } from './test-speed-cloudflare.js';
|
|
15
|
+
* const downloadSpeed = await testDownloadSpeed(false);
|
|
16
|
+
* console.log(downloadSpeed); // e.g., "12.3"
|
|
17
|
+
*/
|
|
18
|
+
export async function testDownloadSpeed(showMessage = true) {
|
|
19
|
+
var spinner;
|
|
20
|
+
if (showMessage)
|
|
21
|
+
spinner = ora('Testing download speed in MB/s using Cloudflare, runs for 1 minute').start();
|
|
22
|
+
|
|
23
|
+
// globally install @cloudflare/speedtest
|
|
24
|
+
await execSync('npm i -g @cloudflare/speedtest');
|
|
25
|
+
|
|
26
|
+
const result = await new Promise((resolve) => {
|
|
27
|
+
const child = spawn('node', [
|
|
28
|
+
'-e',
|
|
29
|
+
"import SpeedTest from '@cloudflare/speedtest'; new SpeedTest({iterations: 1}).onFinish = r => console.log((r.getDownloadBandwidth() / 8388608).toFixed(1))"
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
let output = '';
|
|
33
|
+
child.stdout.on('data', (data) => {
|
|
34
|
+
output += data.toString();
|
|
35
|
+
});
|
|
36
|
+
// Extract last number from output
|
|
37
|
+
child.on('close', () => {
|
|
38
|
+
resolve(output.trim().split('\n').pop().match(/(\d+(\.\d+)?)/)?.[0]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (showMessage) spinner.succeed(result + ' MB/s');
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// try{
|
|
48
|
+
// run if file is executed directly
|
|
49
|
+
// if (process?.env.npm_lifecycle_event?.length > 0 || import.meta.url === `file://${process.argv[1]}` || import.meta.url === process.argv[1] || import.meta.url === `file://${process.cwd()}/${process.argv[1]}`)
|
|
50
|
+
testDownloadSpeed();
|
|
51
|
+
// } catch { }
|