about-system 0.0.5 → 0.0.9
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} +169 -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.9",
|
|
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,16 +15,15 @@
|
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
import os from 'os';
|
|
23
|
+
import fs from 'fs';
|
|
24
|
+
import path from 'path';
|
|
25
|
+
import { execSync } from 'child_process';
|
|
26
|
+
import https from 'https';
|
|
28
27
|
|
|
29
28
|
// Cache configuration
|
|
30
29
|
const CACHE_FILE = path.join(os.tmpdir(), 'systeminfo-cache.json');
|
|
@@ -337,9 +336,9 @@ const infoFunctions = {
|
|
|
337
336
|
const addresses = [];
|
|
338
337
|
|
|
339
338
|
for (const name of Object.keys(interfaces)) {
|
|
340
|
-
for (const
|
|
341
|
-
if (
|
|
342
|
-
addresses.push(
|
|
339
|
+
for (const device of interfaces[name]) {
|
|
340
|
+
if (device.family === 'IPv4' && !device.internal) {
|
|
341
|
+
addresses.push(device.address);
|
|
343
342
|
}
|
|
344
343
|
}
|
|
345
344
|
}
|
|
@@ -439,7 +438,26 @@ const infoFunctions = {
|
|
|
439
438
|
|
|
440
439
|
let cpuName = '';
|
|
441
440
|
|
|
442
|
-
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) {
|
|
443
461
|
// Try lscpu first (like bash script)
|
|
444
462
|
try {
|
|
445
463
|
const lscpu = execCommand('lscpu');
|
|
@@ -467,7 +485,7 @@ const infoFunctions = {
|
|
|
467
485
|
// Use Node.js os module for other platforms
|
|
468
486
|
const cpus = os.cpus();
|
|
469
487
|
if (cpus.length > 0) {
|
|
470
|
-
cpuName = cpus[0].model;
|
|
488
|
+
cpuName = cpus[0].model.trim().replace(/[\r\n]+/g, ' ');
|
|
471
489
|
}
|
|
472
490
|
}
|
|
473
491
|
|
|
@@ -477,7 +495,7 @@ const infoFunctions = {
|
|
|
477
495
|
}
|
|
478
496
|
|
|
479
497
|
//remove "with ..." from cpuName
|
|
480
|
-
cpuName = cpuName.replace(/with .*/, '');
|
|
498
|
+
cpuName = cpuName.trim().replace(/with .*/, '');
|
|
481
499
|
|
|
482
500
|
const color = colors[settings.colors.cpu] || colors.orange;
|
|
483
501
|
const emoji = settings.display.show_emojis ? '📈 ' : '';
|
|
@@ -490,7 +508,36 @@ const infoFunctions = {
|
|
|
490
508
|
const cached = getCachedValue(this.cache, 'gpu', settings);
|
|
491
509
|
if (cached) return cached;
|
|
492
510
|
|
|
493
|
-
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) {
|
|
494
541
|
try {
|
|
495
542
|
const lspci = execCommand('lspci');
|
|
496
543
|
// Look for VGA and specific GPU brands like the bash script
|
|
@@ -526,7 +573,40 @@ const infoFunctions = {
|
|
|
526
573
|
const cached = getCachedValue(this.cache, 'disk_used', settings);
|
|
527
574
|
if (cached) return cached;
|
|
528
575
|
|
|
529
|
-
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) {
|
|
530
610
|
try {
|
|
531
611
|
const df = execCommand('df -h');
|
|
532
612
|
let diskUsage = '';
|
|
@@ -618,7 +698,44 @@ const infoFunctions = {
|
|
|
618
698
|
const cached = getCachedValue(this.cache, 'top_process', settings);
|
|
619
699
|
if (cached) return cached;
|
|
620
700
|
|
|
621
|
-
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) {
|
|
622
739
|
try {
|
|
623
740
|
const ps = execCommand('ps -eo pcpu,comm --sort=-%cpu --no-headers');
|
|
624
741
|
const lines = ps.split('\n');
|
|
@@ -654,7 +771,36 @@ const infoFunctions = {
|
|
|
654
771
|
const cached = getCachedValue(this.cache, 'device', settings);
|
|
655
772
|
if (cached) return cached;
|
|
656
773
|
|
|
657
|
-
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) {
|
|
658
804
|
try {
|
|
659
805
|
// Check for Android
|
|
660
806
|
if (commandExists('getprop')) {
|
|
@@ -1240,17 +1386,15 @@ function handleSettingsCommand(args) {
|
|
|
1240
1386
|
return true;
|
|
1241
1387
|
}
|
|
1242
1388
|
|
|
1243
|
-
const cacheResetIndex = args.indexOf('--
|
|
1389
|
+
const cacheResetIndex = args.indexOf('--refresh');
|
|
1244
1390
|
if (cacheResetIndex !== -1) {
|
|
1245
1391
|
try {
|
|
1246
1392
|
if (fs.existsSync(CACHE_FILE)) {
|
|
1247
1393
|
fs.unlinkSync(CACHE_FILE);
|
|
1248
1394
|
}
|
|
1249
|
-
console.log('Cache cleared');
|
|
1250
1395
|
} catch (error) {
|
|
1251
1396
|
console.error('Error clearing cache:', error.message);
|
|
1252
1397
|
}
|
|
1253
|
-
return true;
|
|
1254
1398
|
}
|
|
1255
1399
|
|
|
1256
1400
|
const setIndex = args.indexOf('--set');
|
|
@@ -1430,7 +1574,7 @@ Options:
|
|
|
1430
1574
|
--settings-init Initialize settings file with defaults
|
|
1431
1575
|
--settings-show Display current settings
|
|
1432
1576
|
--settings-reset Reset settings to defaults
|
|
1433
|
-
--
|
|
1577
|
+
--refresh Clear the cache file
|
|
1434
1578
|
--set <key> <value> Set a configuration value (use dot notation)
|
|
1435
1579
|
|
|
1436
1580
|
Examples:
|
|
@@ -1490,11 +1634,11 @@ Linux-specific features:
|
|
|
1490
1634
|
}
|
|
1491
1635
|
|
|
1492
1636
|
// Run the script
|
|
1493
|
-
if (
|
|
1637
|
+
// if (import.meta.url === `file://${process.argv[1]}`) {
|
|
1494
1638
|
main().catch(error => {
|
|
1495
1639
|
console.error('Error:', error.message);
|
|
1496
1640
|
process.exit(1);
|
|
1497
1641
|
});
|
|
1498
|
-
}
|
|
1642
|
+
// }
|
|
1499
1643
|
|
|
1500
|
-
|
|
1644
|
+
export { displaySystemInfo, installShellGreeting };
|
|
@@ -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 { }
|