nport 2.0.6 → 2.0.7

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/CHANGELOG.md CHANGED
@@ -5,6 +5,82 @@ All notable changes to NPort will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.0.7] - 2026-01-14
9
+
10
+ ### Added
11
+ - 🌐 **Smart Network Warning System**: Intelligent handling of QUIC/network connectivity issues
12
+ - Automatic detection and filtering of QUIC protocol errors
13
+ - User-friendly warning messages instead of scary red error spam
14
+ - Bilingual support (English & Vietnamese)
15
+ - Smart throttling: Shows warning only after 5 errors, max once per 30 seconds
16
+ - Clear explanations of what's happening and how to fix it
17
+ - Automatic reset when connection is restored
18
+ - 🔒 **Protected Subdomain Support**: Enhanced error handling for reserved subdomains
19
+ - User-friendly error message when trying to create protected subdomains (like `api`)
20
+ - Formatted error output matching existing error style
21
+ - Helpful suggestions to use alternative subdomain names
22
+ - Prevents accidental use of backend service subdomains
23
+
24
+ ### Improved
25
+ - 🔇 **Cleaner Terminal Output**: No more error spam from cloudflared
26
+ - QUIC timeout errors are now silently tracked instead of displayed
27
+ - Network warnings filtered: "failed to accept QUIC stream", "timeout: no recent network activity", etc.
28
+ - Only shows meaningful warnings when there's an actual persistent issue
29
+ - Terminal stays clean and readable during normal operation
30
+ - 📡 **Better User Communication**: Context-aware network issue reporting
31
+ - Explains that QUIC failures are usually not critical
32
+ - Tunnel continues working via HTTP/2 fallback
33
+ - Provides actionable troubleshooting steps
34
+ - Reassures users that the tunnel is still functional
35
+ - ✨ **Better Error Messages**: Enhanced user feedback for protected subdomains
36
+ - Catches `SUBDOMAIN_PROTECTED` errors from backend
37
+ - Formats error messages consistently with other error types
38
+ - Shows actionable options when subdomain is reserved
39
+
40
+ ### Technical Details
41
+ - **Network Error Patterns**: Added detection for 7 common QUIC/network error patterns
42
+ - **State Management**: New network issue tracking in application state
43
+ - `networkIssueCount`: Counter for network errors
44
+ - `lastNetworkWarningTime`: Timestamp tracking for cooldown
45
+ - `shouldShowNetworkWarning()`: Smart decision logic
46
+ - **Configuration**: New `NETWORK_CONFIG` with threshold and cooldown settings
47
+ - **Bilingual Messages**: Complete translations for all network warning messages
48
+ - **Protected Subdomain Handling**: Enhanced error handling in `src/api.js`
49
+ - Added check for `SUBDOMAIN_PROTECTED` error type
50
+ - Consistent formatting with existing error messages
51
+ - Clear user guidance for alternative subdomain choices
52
+
53
+ ### User Experience
54
+ **Before:**
55
+ ```
56
+ [Cloudflared] 2026-01-14T04:33:02Z ERR failed to accept QUIC stream...
57
+ [Cloudflared] 2026-01-14T04:33:03Z ERR failed to accept QUIC stream...
58
+ [Cloudflared] 2026-01-14T04:33:04Z ERR failed to accept QUIC stream...
59
+ [Cloudflared] 2026-01-14T04:33:05Z ERR failed to accept QUIC stream...
60
+ ```
61
+
62
+ **After:**
63
+ ```
64
+ ✔ [1/2] Connection established...
65
+ ✔ [2/2] Compression enabled...
66
+
67
+ ⚠️ NETWORK CONNECTIVITY ISSUE DETECTED
68
+ Cloudflared is having trouble maintaining a stable connection...
69
+ 📡 Your tunnel is still working, but connection quality may be affected.
70
+
71
+ 💡 Possible reasons:
72
+ • Unstable internet connection or high packet loss
73
+ • Firewall/Router blocking UDP traffic (QUIC protocol)
74
+ • ISP throttling or network congestion
75
+
76
+ 🔧 What to try:
77
+ • Check your internet connection stability
78
+ • Try connecting from a different network
79
+ • Disable VPN/Proxy if you're using one
80
+
81
+ ℹ️ This is usually not critical - your tunnel should continue working normally.
82
+ ```
83
+
8
84
  ## [2.0.6] - 2026-01-13
9
85
 
10
86
  ### Added
@@ -110,6 +186,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
110
186
 
111
187
  ## Version Upgrade Guide
112
188
 
189
+ ### From 2.0.6 to 2.0.7
190
+
191
+ ```bash
192
+ npm install -g nport@latest
193
+ ```
194
+
195
+ **What's New:**
196
+
197
+ 1. **Cleaner Terminal Experience**
198
+ - No more scary red QUIC error spam
199
+ - Smart network warnings when needed
200
+ - Automatic fallback to HTTP/2 when QUIC fails
201
+
202
+ 2. **Better Error Communication**
203
+ - Understand what's happening with your connection
204
+ - Clear explanations in your language (EN/VI)
205
+ - Actionable troubleshooting steps
206
+
207
+ 3. **When You'll See Warnings**
208
+ - Only after multiple network issues (not just one)
209
+ - Maximum once every 30 seconds (no spam)
210
+ - Automatically disappears when connection improves
211
+
212
+ **Breaking Changes:** None - fully backward compatible!
213
+
113
214
  ### From 2.0.5 to 2.0.6
114
215
 
115
216
  ```bash
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nick Pham
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -35,6 +35,17 @@ Perfect for:
35
35
 
36
36
  ## 📦 Installation
37
37
 
38
+ ### Requirements
39
+
40
+ - **Node.js** >= 20.0.0
41
+ - **npm** >= 10.0.0
42
+
43
+ Check your versions:
44
+ ```bash
45
+ node --version
46
+ npm --version
47
+ ```
48
+
38
49
  ### NPM (Recommended)
39
50
 
40
51
  ```bash
@@ -406,8 +417,12 @@ If you find NPort useful, please consider supporting the project:
406
417
  ## 🙏 Credits
407
418
 
408
419
  - Created by [Nick Pham](https://github.com/tuanngocptn) from Vietnam
409
- - Powered by [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)
410
420
  - Inspired by [ngrok](https://ngrok.com) and [localtunnel](https://github.com/localtunnel/localtunnel)
421
+ - Powered by [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)
422
+
423
+ <a href="https://www.cloudflare.com" target="_blank">
424
+ <img src="https://nport.link/assets/webp/cloudflare-logo-black.webp" alt="Cloudflare" height="60">
425
+ </a>
411
426
 
412
427
  ## 🔗 Links
413
428
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nport",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "description": "Free & open source ngrok alternative - Tunnel HTTP/HTTPS connections via Cloudflare Edge with custom subdomains",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -8,8 +8,8 @@
8
8
  "nport": "index.js"
9
9
  },
10
10
  "engines": {
11
- "node": ">=18.0.0",
12
- "npm": ">=8.0.0"
11
+ "node": ">=20.0.0",
12
+ "npm": ">=10.0.0"
13
13
  },
14
14
  "keywords": [
15
15
  "ngrok",
package/src/api.js CHANGED
@@ -38,6 +38,21 @@ export class APIClient {
38
38
  if (error.response?.data?.error) {
39
39
  const errorMsg = error.response.data.error;
40
40
 
41
+ // Check for protected subdomain (reserved for production services)
42
+ if (errorMsg.includes("SUBDOMAIN_PROTECTED:")) {
43
+ return new Error(
44
+ `Subdomain "${subdomain}" is already taken or in use.\n\n` +
45
+ chalk.yellow(`💡 Try one of these options:\n`) +
46
+ chalk.gray(` 1. Choose a different subdomain: `) +
47
+ chalk.cyan(`nport ${state.port || CONFIG.DEFAULT_PORT} -s ${subdomain}-v2\n`) +
48
+ chalk.gray(` 2. Use a random subdomain: `) +
49
+ chalk.cyan(`nport ${state.port || CONFIG.DEFAULT_PORT}\n`) +
50
+ chalk.gray(
51
+ ` 3. Wait a few minutes and retry if you just stopped a tunnel with this name`
52
+ )
53
+ );
54
+ }
55
+
41
56
  // Check for subdomain in use (active tunnel)
42
57
  if (
43
58
  errorMsg.includes("SUBDOMAIN_IN_USE:") ||
package/src/binary.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { spawn } from "child_process";
2
2
  import chalk from "chalk";
3
3
  import fs from "fs";
4
- import { LOG_PATTERNS } from "./config.js";
4
+ import { LOG_PATTERNS, NETWORK_CONFIG } from "./config.js";
5
5
  import { state } from "./state.js";
6
6
  import { UI } from "./ui.js";
7
7
  import { lang } from "./lang.js";
@@ -52,11 +52,19 @@ export class BinaryManager {
52
52
  return;
53
53
  }
54
54
 
55
+ // Check for network warnings (QUIC/connectivity issues)
56
+ if (LOG_PATTERNS.NETWORK_WARNING.some((pattern) => msg.includes(pattern))) {
57
+ this.handleNetworkWarning(msg);
58
+ return; // Don't show the raw error to user
59
+ }
60
+
55
61
  // Show success messages with connection count
56
62
  if (LOG_PATTERNS.SUCCESS.some((pattern) => msg.includes(pattern))) {
57
63
  const count = state.incrementConnection();
58
64
 
65
+ // Reset network issue count when connection succeeds
59
66
  if (count === 1) {
67
+ state.resetNetworkIssues();
60
68
  console.log(chalk.green(lang.t("connection1")));
61
69
  } else if (count === 4) {
62
70
  console.log(chalk.green(lang.t("connection2")));
@@ -72,6 +80,36 @@ export class BinaryManager {
72
80
  }
73
81
  }
74
82
 
83
+ static handleNetworkWarning(msg) {
84
+ const count = state.incrementNetworkIssue();
85
+
86
+ // Show user-friendly warning after threshold is reached
87
+ if (
88
+ state.shouldShowNetworkWarning(
89
+ NETWORK_CONFIG.WARNING_THRESHOLD,
90
+ NETWORK_CONFIG.WARNING_COOLDOWN
91
+ )
92
+ ) {
93
+ this.displayNetworkWarning();
94
+ }
95
+ }
96
+
97
+ static displayNetworkWarning() {
98
+ console.log(chalk.yellow(lang.t("networkIssueTitle")));
99
+ console.log(chalk.gray(lang.t("networkIssueDesc")));
100
+ console.log(chalk.cyan(lang.t("networkIssueTunnel")));
101
+ console.log(chalk.yellow(lang.t("networkIssueReasons")));
102
+ console.log(chalk.gray(lang.t("networkIssueReason1")));
103
+ console.log(chalk.gray(lang.t("networkIssueReason2")));
104
+ console.log(chalk.gray(lang.t("networkIssueReason3")));
105
+ console.log(chalk.yellow(lang.t("networkIssueFix")));
106
+ console.log(chalk.gray(lang.t("networkIssueFix1")));
107
+ console.log(chalk.gray(lang.t("networkIssueFix2")));
108
+ console.log(chalk.gray(lang.t("networkIssueFix3")));
109
+ console.log(chalk.gray(lang.t("networkIssueFix4")));
110
+ console.log(chalk.blue(lang.t("networkIssueIgnore")));
111
+ }
112
+
75
113
  static handleError(err, spinner) {
76
114
  if (spinner) {
77
115
  spinner.fail("Failed to spawn cloudflared process.");
package/src/config.js CHANGED
@@ -46,6 +46,18 @@ export const PATHS = {
46
46
  export const LOG_PATTERNS = {
47
47
  SUCCESS: ["Registered tunnel connection"],
48
48
  ERROR: ["ERR", "error"],
49
+
50
+ // Network-related warnings (not critical errors)
51
+ NETWORK_WARNING: [
52
+ "failed to accept QUIC stream",
53
+ "failed to dial to edge with quic",
54
+ "failed to accept incoming stream requests",
55
+ "Failed to dial a quic connection",
56
+ "timeout: no recent network activity",
57
+ "failed to dial to edge",
58
+ "quic:",
59
+ ],
60
+
49
61
  IGNORE: [
50
62
  "Cannot determine default origin certificate path",
51
63
  "No file cert.pem",
@@ -65,6 +77,12 @@ export const LOG_PATTERNS = {
65
77
  ],
66
78
  };
67
79
 
80
+ // Network warning configuration
81
+ export const NETWORK_CONFIG = {
82
+ WARNING_THRESHOLD: 5, // Show warning after 5 network errors
83
+ WARNING_COOLDOWN: 30000, // Only show warning every 30 seconds
84
+ };
85
+
68
86
  // Computed constants
69
87
  export const TUNNEL_TIMEOUT_MS = CONFIG.TUNNEL_TIMEOUT_HOURS * 60 * 60 * 1000;
70
88
 
package/src/lang.js CHANGED
@@ -62,6 +62,21 @@ const TRANSLATIONS = {
62
62
  languageVietnamese: "2. Tiếng Việt (Vietnamese)",
63
63
  languageInvalid: "Invalid choice. Using English by default.",
64
64
  languageSaved: "✔ Language preference saved!",
65
+
66
+ // Network warnings
67
+ networkIssueTitle: "\n⚠️ NETWORK CONNECTIVITY ISSUE DETECTED",
68
+ networkIssueDesc: " Cloudflared is having trouble maintaining a stable connection to Cloudflare's edge servers.",
69
+ networkIssueTunnel: " 📡 Your tunnel is still working, but connection quality may be affected.",
70
+ networkIssueReasons: "\n 💡 Possible reasons:",
71
+ networkIssueReason1: " • Unstable internet connection or high packet loss",
72
+ networkIssueReason2: " • Firewall/Router blocking UDP traffic (QUIC protocol)",
73
+ networkIssueReason3: " • ISP throttling or network congestion",
74
+ networkIssueFix: "\n 🔧 What to try:",
75
+ networkIssueFix1: " • Check your internet connection stability",
76
+ networkIssueFix2: " • Try connecting from a different network",
77
+ networkIssueFix3: " • Disable VPN/Proxy if you're using one",
78
+ networkIssueFix4: " • The tunnel will automatically fallback to HTTP/2 if QUIC fails",
79
+ networkIssueIgnore: "\n ℹ️ This is usually not critical - your tunnel should continue working normally.\n",
65
80
  },
66
81
 
67
82
  vi: {
@@ -104,7 +119,7 @@ const TRANSLATIONS = {
104
119
 
105
120
  // Version
106
121
  versionTitle: "NPort v{version}",
107
- versionSubtitle: "Hơn cả Ngrok - Ma-de in Ziệt Nam",
122
+ versionSubtitle: "Hơn cả Ngrok - Ma-de in Việt Nam",
108
123
  versionLatest: "🎉 Chúc mừng! Đang cùng server với bản mới nhất!",
109
124
  versionAvailable: "🌟 Vèo vèo: Có bản mới v{version} vừa cập bến!",
110
125
  versionUpdate: "Update khẩn trương lẹ làng: ",
@@ -117,6 +132,21 @@ const TRANSLATIONS = {
117
132
  languageVietnamese: "2. Tiếng Việt (Đỉnh của chóp)",
118
133
  languageInvalid: "Ơ hơ, chọn sai rồi! Mặc định Tiếng Việt luôn cho nóng.",
119
134
  languageSaved: "🎯 Xong rồi! Lưu ngôn ngữ thành công!",
135
+
136
+ // Network warnings
137
+ networkIssueTitle: "\n⚠️ PHÁT HIỆN VẤN ĐỀ MẠNG",
138
+ networkIssueDesc: " Cloudflared đang gặp khó khăn khi giữ kết nối ổn định tới Cloudflare edge servers.",
139
+ networkIssueTunnel: " 📡 Tunnel của bạn vẫn hoạt động, nhưng chất lượng kết nối có thể bị ảnh hưởng.",
140
+ networkIssueReasons: "\n 💡 Có thể do:",
141
+ networkIssueReason1: " • Mạng internet không ổn định hoặc mất gói tin",
142
+ networkIssueReason2: " • Firewall/Router chặn UDP traffic (giao thức QUIC)",
143
+ networkIssueReason3: " • Nhà mạng throttle hoặc tắc nghẽn mạng",
144
+ networkIssueFix: "\n 🔧 Thử các cách sau:",
145
+ networkIssueFix1: " • Kiểm tra kết nối internet của bạn",
146
+ networkIssueFix2: " • Thử đổi sang mạng khác (ví dụ: 4G/5G)",
147
+ networkIssueFix3: " • Tắt VPN/Proxy nếu đang bật",
148
+ networkIssueFix4: " • Tunnel sẽ tự động chuyển sang HTTP/2 nếu QUIC fail",
149
+ networkIssueIgnore: "\n ℹ️ Lỗi này thường không nghiêm trọng - tunnel vẫn hoạt động bình thường.\n",
120
150
  }
121
151
  };
122
152
 
package/src/state.js CHANGED
@@ -13,6 +13,11 @@ class TunnelState {
13
13
  this.connectionCount = 0;
14
14
  this.startTime = null;
15
15
  this.updateInfo = null;
16
+
17
+ // Network issue tracking
18
+ this.networkIssueCount = 0;
19
+ this.lastNetworkWarningTime = 0;
20
+ this.networkWarningShown = false;
16
21
  }
17
22
 
18
23
  setTunnel(tunnelId, subdomain, port, backendUrl = null) {
@@ -62,6 +67,32 @@ class TunnelState {
62
67
  return (Date.now() - this.startTime) / 1000;
63
68
  }
64
69
 
70
+ // Network issue tracking methods
71
+ incrementNetworkIssue() {
72
+ this.networkIssueCount++;
73
+ return this.networkIssueCount;
74
+ }
75
+
76
+ resetNetworkIssues() {
77
+ this.networkIssueCount = 0;
78
+ }
79
+
80
+ shouldShowNetworkWarning(threshold, cooldown) {
81
+ const now = Date.now();
82
+ if (
83
+ this.networkIssueCount >= threshold &&
84
+ now - this.lastNetworkWarningTime > cooldown
85
+ ) {
86
+ this.lastNetworkWarningTime = now;
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+
92
+ setNetworkWarningShown(value) {
93
+ this.networkWarningShown = value;
94
+ }
95
+
65
96
  reset() {
66
97
  this.clearTimeout();
67
98
  this.tunnelId = null;
@@ -72,6 +103,11 @@ class TunnelState {
72
103
  this.connectionCount = 0;
73
104
  this.startTime = null;
74
105
  this.updateInfo = null;
106
+
107
+ // Reset network tracking
108
+ this.networkIssueCount = 0;
109
+ this.lastNetworkWarningTime = 0;
110
+ this.networkWarningShown = false;
75
111
  }
76
112
  }
77
113