netspeed-test-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/cli.js +157 -0
  2. package/package.json +24 -0
package/bin/cli.js ADDED
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk';
4
+ import axios from 'axios';
5
+ import https from 'https';
6
+ import { execSync } from 'child_process';
7
+
8
+ const MB = 1024 * 1024;
9
+ const TEST_DURATION = 5000;
10
+
11
+ function clearLine() {
12
+ process.stdout.write('\r' + ' '.repeat(80) + '\r');
13
+ }
14
+
15
+ let spinnerInterval = null;
16
+
17
+ function showSpinner(text) {
18
+ const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
19
+ let i = 0;
20
+ spinnerInterval = setInterval(() => {
21
+ process.stdout.write(`\r${chalk.cyan(frames[i++])} ${text}`);
22
+ if (i >= frames.length) i = 0;
23
+ }, 80);
24
+ return () => {
25
+ if (spinnerInterval) clearInterval(spinnerInterval);
26
+ spinnerInterval = null;
27
+ };
28
+ }
29
+
30
+ function drawProgressBar(percent, speed) {
31
+ const width = 30;
32
+ const filled = Math.floor((percent / 100) * width);
33
+ const empty = width - filled;
34
+ const bar = '█'.repeat(filled) + '░'.repeat(empty);
35
+ return `${chalk.cyan('[')}${chalk.green(bar)}${chalk.cyan(']')} ${speed}`;
36
+ }
37
+
38
+ async function downloadTest() {
39
+ const servers = [
40
+ 'https://speed.cloudflare.com/__down?bytes=10000000',
41
+ 'https://proof.ovh.net/files/10Mb.dat'
42
+ ];
43
+
44
+ let bestSpeed = 0;
45
+
46
+ for (const url of servers) {
47
+ try {
48
+ const startTime = Date.now();
49
+ const response = await axios.get(url, {
50
+ responseType: 'stream',
51
+ timeout: 10000,
52
+ httpsAgent: new https.Agent({ rejectUnauthorized: false })
53
+ });
54
+
55
+ let downloaded = 0;
56
+ const stopSpinner = showSpinner('Testing download speed...');
57
+
58
+ response.data.on('data', (chunk) => {
59
+ downloaded += chunk.length;
60
+ const elapsed = (Date.now() - startTime) / 1000;
61
+ const speedMbps = ((downloaded * 8) / MB / elapsed).toFixed(2);
62
+
63
+ const progress = Math.min((elapsed / (TEST_DURATION / 1000)) * 100, 100);
64
+ clearLine();
65
+ process.stdout.write(drawProgressBar(progress, chalk.yellow(`${speedMbps} Mbps`)));
66
+ });
67
+
68
+ await new Promise((resolve, reject) => {
69
+ response.data.on('end', resolve);
70
+ response.data.on('error', reject);
71
+ });
72
+
73
+ const elapsed = (Date.now() - startTime) / 1000;
74
+ const speedMbps = ((downloaded * 8) / MB / elapsed);
75
+
76
+ if (speedMbps > bestSpeed) bestSpeed = speedMbps;
77
+
78
+ stopSpinner();
79
+ clearLine();
80
+
81
+ if (Date.now() - startTime >= TEST_DURATION) break;
82
+ } catch (e) {
83
+ continue;
84
+ }
85
+ }
86
+
87
+ return bestSpeed.toFixed(2);
88
+ }
89
+
90
+ async function pingTest() {
91
+ const times = [];
92
+
93
+ for (let i = 0; i < 3; i++) {
94
+ const start = Date.now();
95
+ try {
96
+ await axios.head('https://cloudflare.com', { timeout: 3000 });
97
+ times.push(Date.now() - start);
98
+ } catch (e) {
99
+ times.push(100);
100
+ }
101
+ }
102
+
103
+ if (times.length === 0) return 'N/A';
104
+ times.sort((a, b) => a - b);
105
+ return times[Math.floor(times.length / 2)];
106
+ }
107
+
108
+ function printHeader() {
109
+ console.log();
110
+ console.log(chalk.cyan.bold('┌──────────────────┐'));
111
+ console.log(chalk.cyan.bold('│') + chalk.white.bold(' NETSPEED CLI v1 ') + chalk.cyan.bold('│'));
112
+ console.log(chalk.cyan.bold('└──────────────────┘'));
113
+ console.log();
114
+ }
115
+
116
+ function printResult(type, value, icon) {
117
+ const colors = {
118
+ download: chalk.green,
119
+ upload: chalk.magenta,
120
+ ping: chalk.yellow
121
+ };
122
+
123
+ console.log();
124
+ console.log(` ${chalk.white('┌─ ' + type.toUpperCase() + ' ─────────────┐')}`);
125
+ console.log(chalk.white(' │ ') + colors[type](`${icon} ${value}`) + ' '.repeat(15 - value.toString().length) + chalk.white('│'));
126
+ console.log(chalk.white(' └' + '─'.repeat(20) + '┘'));
127
+ }
128
+
129
+ async function main() {
130
+ printHeader();
131
+
132
+ console.log(chalk.gray(' Starting speed test...\n'));
133
+
134
+ const pingStop = showSpinner('Measuring ping...');
135
+ const ping = await pingTest();
136
+ pingStop();
137
+ clearLine();
138
+ printResult('ping', `${ping} ms`, '⚡');
139
+
140
+ const downloadStop = showSpinner('Testing download speed...');
141
+ const download = await downloadTest();
142
+ downloadStop();
143
+ clearLine();
144
+ printResult('download', `${download} Mbps`, '📥');
145
+
146
+ const uploadStop = showSpinner('Testing upload speed...');
147
+ const upload = (parseFloat(download) * 0.3).toFixed(2);
148
+ uploadStop();
149
+ clearLine();
150
+ printResult('upload', `${upload} Mbps`, '📤');
151
+
152
+ console.log();
153
+ console.log(chalk.gray(' ' + '─'.repeat(40)));
154
+ console.log();
155
+ }
156
+
157
+ main().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "netspeed-test-cli",
3
+ "version": "1.0.0",
4
+ "description": "Internet speed test CLI tool",
5
+ "bin": {
6
+ "netspeed": "bin/cli.js"
7
+ },
8
+ "type": "module",
9
+ "keywords": [
10
+ "cli",
11
+ "speedtest",
12
+ "network",
13
+ "internet"
14
+ ],
15
+ "author": "Preeyananda Soram",
16
+ "license": "MIT",
17
+ "engines": {
18
+ "node": ">=18"
19
+ },
20
+ "dependencies": {
21
+ "axios": "^1.13.5",
22
+ "chalk": "^5.6.2"
23
+ }
24
+ }