nport 2.0.7 → 2.1.1
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 +173 -0
- package/README.md +42 -32
- package/dist/analytics.d.ts +59 -0
- package/dist/analytics.js +193 -0
- package/dist/analytics.js.map +1 -0
- package/dist/api.d.ts +20 -0
- package/dist/api.js +85 -0
- package/dist/api.js.map +1 -0
- package/dist/args.d.ts +44 -0
- package/dist/args.js +127 -0
- package/dist/args.js.map +1 -0
- package/dist/bin-manager.d.ts +1 -0
- package/dist/bin-manager.js +209 -0
- package/dist/bin-manager.js.map +1 -0
- package/dist/binary.d.ts +42 -0
- package/dist/binary.js +119 -0
- package/dist/binary.js.map +1 -0
- package/dist/config-manager.d.ts +54 -0
- package/dist/config-manager.js +129 -0
- package/dist/config-manager.js.map +1 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +61 -0
- package/dist/constants.js +86 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +92 -0
- package/dist/index.js.map +1 -0
- package/dist/lang.d.ts +38 -0
- package/dist/lang.js +217 -0
- package/dist/lang.js.map +1 -0
- package/dist/state.d.ts +82 -0
- package/dist/state.js +139 -0
- package/dist/state.js.map +1 -0
- package/dist/tunnel.d.ts +16 -0
- package/dist/tunnel.js +101 -0
- package/dist/tunnel.js.map +1 -0
- package/dist/types/analytics.d.ts +91 -0
- package/dist/types/analytics.js +8 -0
- package/dist/types/analytics.js.map +1 -0
- package/dist/types/config.d.ts +89 -0
- package/dist/types/config.js +8 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/i18n.d.ts +75 -0
- package/dist/types/i18n.js +5 -0
- package/dist/types/i18n.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/tunnel.d.ts +74 -0
- package/dist/types/tunnel.js +8 -0
- package/dist/types/tunnel.js.map +1 -0
- package/dist/types/version.d.ts +25 -0
- package/dist/types/version.js +5 -0
- package/dist/types/version.js.map +1 -0
- package/dist/ui.d.ts +54 -0
- package/dist/ui.js +120 -0
- package/dist/ui.js.map +1 -0
- package/dist/version.d.ts +16 -0
- package/dist/version.js +49 -0
- package/dist/version.js.map +1 -0
- package/package.json +18 -7
- package/scripts/postinstall.js +25 -0
- package/index.js +0 -110
- package/src/analytics.js +0 -265
- package/src/api.js +0 -104
- package/src/args.js +0 -122
- package/src/bin-manager.js +0 -379
- package/src/binary.js +0 -126
- package/src/config-manager.js +0 -139
- package/src/config.js +0 -88
- package/src/lang.js +0 -293
- package/src/state.js +0 -115
- package/src/tunnel.js +0 -116
- package/src/ui.js +0 -103
- package/src/version.js +0 -56
package/dist/lang.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
2
|
+
import { AVAILABLE_LANGUAGES } from './constants.js';
|
|
3
|
+
import { configManager } from './config-manager.js';
|
|
4
|
+
/**
|
|
5
|
+
* Translation strings for all supported languages
|
|
6
|
+
*/
|
|
7
|
+
const TRANSLATIONS = {
|
|
8
|
+
en: {
|
|
9
|
+
header: 'N P O R T ⚡️ Free & Open Source from Vietnam ❤️',
|
|
10
|
+
creatingTunnel: 'Creating tunnel for port {port}...',
|
|
11
|
+
checkingUpdates: 'Checking for updates...',
|
|
12
|
+
tunnelLive: '🚀 WE LIVE BABY!',
|
|
13
|
+
connection1: ' ✔ [1/2] Connection established...',
|
|
14
|
+
connection2: ' ✔ [2/2] Compression enabled...',
|
|
15
|
+
timeRemaining: '⏱️ Time: {hours}h remaining',
|
|
16
|
+
footerTitle: '🔥 KEEP THE VIBE ALIVE?',
|
|
17
|
+
footerSubtitle: '(Made with ❤️ in Vietnam)',
|
|
18
|
+
dropStar: '⭐️ Drop a Star: ',
|
|
19
|
+
sendCoffee: '☕️ Buy Coffee: ',
|
|
20
|
+
newVersion: '🚨 NEW VERSION (v{version}) detected!',
|
|
21
|
+
updateCommand: '> npm install -g nport@latest',
|
|
22
|
+
tunnelShutdown: '🛑 TUNNEL SHUTDOWN.',
|
|
23
|
+
cleaningUp: 'Cleaning up... ',
|
|
24
|
+
cleanupDone: 'Done.',
|
|
25
|
+
cleanupFailed: 'Failed.',
|
|
26
|
+
subdomainReleased: 'Subdomain... Released. 🗑️',
|
|
27
|
+
serverBusy: '(Server might be down or busy)',
|
|
28
|
+
goodbyeTitle: '👋 BEFORE YOU GO...',
|
|
29
|
+
goodbyeMessage: 'Thanks for using NPort!',
|
|
30
|
+
website: '🌐 Website: ',
|
|
31
|
+
author: '👤 Author: ',
|
|
32
|
+
changeLanguage: '🌍 Language: ',
|
|
33
|
+
changeLanguageHint: 'nport --language',
|
|
34
|
+
versionTitle: 'NPort v{version}',
|
|
35
|
+
versionSubtitle: 'Free & open source ngrok alternative',
|
|
36
|
+
versionLatest: '✔ You\'re running the latest version!',
|
|
37
|
+
versionAvailable: '🚨 New version available: v{version}',
|
|
38
|
+
versionUpdate: 'Update now: ',
|
|
39
|
+
learnMore: 'Learn more: ',
|
|
40
|
+
languagePrompt: '\n🌍 Language Selection / Chọn ngôn ngữ\n',
|
|
41
|
+
languageQuestion: 'Choose your language (1-2): ',
|
|
42
|
+
languageEnglish: '1. English',
|
|
43
|
+
languageVietnamese: '2. Tiếng Việt (Vietnamese)',
|
|
44
|
+
languageInvalid: 'Invalid choice. Using English by default.',
|
|
45
|
+
languageSaved: '✔ Language preference saved!',
|
|
46
|
+
networkIssueTitle: '\n⚠️ NETWORK CONNECTIVITY ISSUE DETECTED',
|
|
47
|
+
networkIssueDesc: ' Cloudflared is having trouble maintaining a stable connection to Cloudflare\'s edge servers.',
|
|
48
|
+
networkIssueTunnel: ' 📡 Your tunnel is still working, but connection quality may be affected.',
|
|
49
|
+
networkIssueReasons: '\n 💡 Possible reasons:',
|
|
50
|
+
networkIssueReason1: ' • Unstable internet connection or high packet loss',
|
|
51
|
+
networkIssueReason2: ' • Firewall/Router blocking UDP traffic (QUIC protocol)',
|
|
52
|
+
networkIssueReason3: ' • ISP throttling or network congestion',
|
|
53
|
+
networkIssueFix: '\n 🔧 What to try:',
|
|
54
|
+
networkIssueFix1: ' • Check your internet connection stability',
|
|
55
|
+
networkIssueFix2: ' • Try connecting from a different network',
|
|
56
|
+
networkIssueFix3: ' • Disable VPN/Proxy if you\'re using one',
|
|
57
|
+
networkIssueFix4: ' • The tunnel will automatically fallback to HTTP/2 if QUIC fails',
|
|
58
|
+
networkIssueIgnore: '\n ℹ️ This is usually not critical - your tunnel should continue working normally.\n',
|
|
59
|
+
},
|
|
60
|
+
vi: {
|
|
61
|
+
header: 'N P O R T ⚡️ Việt Nam Mãi Đỉnh ❤️',
|
|
62
|
+
creatingTunnel: '🛠️ Đang khởi động cổng {port}... Chuẩn bị bay nào!',
|
|
63
|
+
checkingUpdates: '🔍 Đang dò la bản cập nhật mới... Đợi tí sắp có quà!',
|
|
64
|
+
tunnelLive: '🚀 BẬT MODE TỐC HÀNH! ĐANG BAY RỒI NÈ!',
|
|
65
|
+
connection1: ' ✔ [1/2] Đang cắm dây mạng vũ trụ...',
|
|
66
|
+
connection2: ' ✔ [2/2] Đang bơm siêu nén khí tốc độ ánh sáng...',
|
|
67
|
+
timeRemaining: '⏱️ Tăng tốc thần sầu: Còn {hours}h để quẩy!',
|
|
68
|
+
footerTitle: '🔥 LƯU DANH SỬ SÁCH! ĐỪNG QUÊN STAR ⭐️',
|
|
69
|
+
footerSubtitle: '(Made in Việt Nam, chuẩn không cần chỉnh! ❤️)',
|
|
70
|
+
dropStar: '⭐️ Thả Star: ',
|
|
71
|
+
sendCoffee: '☕️ Tặng Coffee: ',
|
|
72
|
+
newVersion: '🚀 BẢN MỚI (v{version}) vừa hạ cánh!',
|
|
73
|
+
updateCommand: '💡 Gõ liền: npm install -g nport@latest',
|
|
74
|
+
tunnelShutdown: '🛑 Đã tới giờ \'chốt\' deal rồi cả nhà ơi...',
|
|
75
|
+
cleaningUp: 'Đang dọn dẹp chiến trường... 🧹',
|
|
76
|
+
cleanupDone: 'Xịn xò! Đã dọn xong rồi nè.',
|
|
77
|
+
cleanupFailed: 'Oằn trời, dọn không nổi!',
|
|
78
|
+
subdomainReleased: 'Subdomain... Xí xoá! Tạm biệt nhé 🗑️✨',
|
|
79
|
+
serverBusy: '(Có thể server đang bận order trà sữa)',
|
|
80
|
+
goodbyeTitle: '👋 GẶP LẠI BẠN Ở ĐƯỜNG BĂNG KHÁC...',
|
|
81
|
+
goodbyeMessage: 'Cảm ơn đã quẩy NPort! Lần sau chơi tiếp nha 😘',
|
|
82
|
+
website: '🌐 Sân chơi chính: ',
|
|
83
|
+
author: '👤 Nhà tài trợ: ',
|
|
84
|
+
changeLanguage: '🌍 Đổi ngôn ngữ: ',
|
|
85
|
+
changeLanguageHint: 'nport --language',
|
|
86
|
+
versionTitle: 'NPort v{version}',
|
|
87
|
+
versionSubtitle: 'Hơn cả Ngrok - Ma-de in Việt Nam',
|
|
88
|
+
versionLatest: '🎉 Chúc mừng! Đang cùng server với bản mới nhất!',
|
|
89
|
+
versionAvailable: '🌟 Vèo vèo: Có bản mới v{version} vừa cập bến!',
|
|
90
|
+
versionUpdate: 'Update khẩn trương lẹ làng: ',
|
|
91
|
+
learnMore: 'Khám phá thêm cho nóng: ',
|
|
92
|
+
languagePrompt: '\n🌍 Chọn lựa ngôn ngữ ngay bên dưới nào!\n',
|
|
93
|
+
languageQuestion: 'Chớp lấy một lựa chọn nha (1-2): ',
|
|
94
|
+
languageEnglish: '1. English (Chuẩn quốc tế!)',
|
|
95
|
+
languageVietnamese: '2. Tiếng Việt (Đỉnh của chóp)',
|
|
96
|
+
languageInvalid: 'Ơ hơ, chọn sai rồi! Mặc định Tiếng Việt luôn cho nóng.',
|
|
97
|
+
languageSaved: '🎯 Xong rồi! Lưu ngôn ngữ thành công!',
|
|
98
|
+
networkIssueTitle: '\n⚠️ PHÁT HIỆN VẤN ĐỀ MẠNG',
|
|
99
|
+
networkIssueDesc: ' Cloudflared đang gặp khó khăn khi giữ kết nối ổn định tới Cloudflare edge servers.',
|
|
100
|
+
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.',
|
|
101
|
+
networkIssueReasons: '\n 💡 Có thể do:',
|
|
102
|
+
networkIssueReason1: ' • Mạng internet không ổn định hoặc mất gói tin',
|
|
103
|
+
networkIssueReason2: ' • Firewall/Router chặn UDP traffic (giao thức QUIC)',
|
|
104
|
+
networkIssueReason3: ' • Nhà mạng throttle hoặc tắc nghẽn mạng',
|
|
105
|
+
networkIssueFix: '\n 🔧 Thử các cách sau:',
|
|
106
|
+
networkIssueFix1: ' • Kiểm tra kết nối internet của bạn',
|
|
107
|
+
networkIssueFix2: ' • Thử đổi sang mạng khác (ví dụ: 4G/5G)',
|
|
108
|
+
networkIssueFix3: ' • Tắt VPN/Proxy nếu đang bật',
|
|
109
|
+
networkIssueFix4: ' • Tunnel sẽ tự động chuyển sang HTTP/2 nếu QUIC fail',
|
|
110
|
+
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',
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Language Manager
|
|
115
|
+
*/
|
|
116
|
+
class LanguageManager {
|
|
117
|
+
currentLanguage = 'en';
|
|
118
|
+
availableLanguages = AVAILABLE_LANGUAGES;
|
|
119
|
+
/**
|
|
120
|
+
* Gets a translated string with variable substitution.
|
|
121
|
+
*/
|
|
122
|
+
t(key, vars = {}) {
|
|
123
|
+
const translations = TRANSLATIONS[this.currentLanguage] || TRANSLATIONS.en;
|
|
124
|
+
let text = translations[key] || TRANSLATIONS.en[key] || key;
|
|
125
|
+
Object.keys(vars).forEach(varKey => {
|
|
126
|
+
const value = vars[varKey];
|
|
127
|
+
if (value !== undefined) {
|
|
128
|
+
text = text.replace(`{${varKey}}`, String(value));
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return text;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Loads saved language preference.
|
|
135
|
+
*/
|
|
136
|
+
loadLanguagePreference() {
|
|
137
|
+
const lang = configManager.getLanguage();
|
|
138
|
+
if (lang && this.availableLanguages.includes(lang)) {
|
|
139
|
+
return lang;
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Saves language preference.
|
|
145
|
+
*/
|
|
146
|
+
saveLanguagePreference(lang) {
|
|
147
|
+
configManager.setLanguage(lang);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Sets the current language.
|
|
151
|
+
*/
|
|
152
|
+
setLanguage(lang) {
|
|
153
|
+
if (this.availableLanguages.includes(lang)) {
|
|
154
|
+
this.currentLanguage = lang;
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Gets the current language code.
|
|
161
|
+
*/
|
|
162
|
+
getLanguage() {
|
|
163
|
+
return this.currentLanguage;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Prompts user to select a language.
|
|
167
|
+
*/
|
|
168
|
+
async promptLanguageSelection() {
|
|
169
|
+
return new Promise((resolve) => {
|
|
170
|
+
const rl = readline.createInterface({
|
|
171
|
+
input: process.stdin,
|
|
172
|
+
output: process.stdout
|
|
173
|
+
});
|
|
174
|
+
console.log(this.t('languagePrompt'));
|
|
175
|
+
console.log(` ${this.t('languageEnglish')}`);
|
|
176
|
+
console.log(` ${this.t('languageVietnamese')}\n`);
|
|
177
|
+
rl.question(`${this.t('languageQuestion')}`, (answer) => {
|
|
178
|
+
rl.close();
|
|
179
|
+
const choice = answer.trim();
|
|
180
|
+
let selectedLang = 'en';
|
|
181
|
+
if (choice === '1') {
|
|
182
|
+
selectedLang = 'en';
|
|
183
|
+
}
|
|
184
|
+
else if (choice === '2') {
|
|
185
|
+
selectedLang = 'vi';
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
console.log(`\n${this.t('languageInvalid')}\n`);
|
|
189
|
+
}
|
|
190
|
+
this.setLanguage(selectedLang);
|
|
191
|
+
this.saveLanguagePreference(selectedLang);
|
|
192
|
+
console.log(`${this.t('languageSaved')}\n`);
|
|
193
|
+
resolve(selectedLang);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Initializes the language system.
|
|
199
|
+
*/
|
|
200
|
+
async initialize(cliLanguage = null) {
|
|
201
|
+
if (cliLanguage && cliLanguage !== 'prompt' && this.setLanguage(cliLanguage)) {
|
|
202
|
+
this.saveLanguagePreference(cliLanguage);
|
|
203
|
+
return cliLanguage;
|
|
204
|
+
}
|
|
205
|
+
if (cliLanguage === 'prompt') {
|
|
206
|
+
return await this.promptLanguageSelection();
|
|
207
|
+
}
|
|
208
|
+
const savedLang = this.loadLanguagePreference();
|
|
209
|
+
if (savedLang) {
|
|
210
|
+
this.setLanguage(savedLang);
|
|
211
|
+
return savedLang;
|
|
212
|
+
}
|
|
213
|
+
return await this.promptLanguageSelection();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
export const lang = new LanguageManager();
|
|
217
|
+
//# sourceMappingURL=lang.js.map
|
package/dist/lang.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lang.js","sourceRoot":"","sources":["../src/lang.ts"],"names":[],"mappings":"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"}
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ChildProcess } from 'child_process';
|
|
2
|
+
import type { UpdateCheckResult } from './types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Application State Manager
|
|
5
|
+
*
|
|
6
|
+
* Singleton class that manages all runtime state for the tunnel.
|
|
7
|
+
*/
|
|
8
|
+
declare class TunnelState {
|
|
9
|
+
tunnelId: string | null;
|
|
10
|
+
subdomain: string | null;
|
|
11
|
+
port: number | null;
|
|
12
|
+
backendUrl: string | null;
|
|
13
|
+
tunnelProcess: ChildProcess | null;
|
|
14
|
+
private timeoutId;
|
|
15
|
+
connectionCount: number;
|
|
16
|
+
startTime: number | null;
|
|
17
|
+
updateInfo: UpdateCheckResult | null;
|
|
18
|
+
private networkIssueCount;
|
|
19
|
+
private lastNetworkWarningTime;
|
|
20
|
+
networkWarningShown: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Sets the tunnel connection information.
|
|
23
|
+
*/
|
|
24
|
+
setTunnel(tunnelId: string | null, subdomain: string, port: number, backendUrl?: string | null): void;
|
|
25
|
+
/**
|
|
26
|
+
* Stores version update information.
|
|
27
|
+
*/
|
|
28
|
+
setUpdateInfo(updateInfo: UpdateCheckResult | null): void;
|
|
29
|
+
/**
|
|
30
|
+
* Stores reference to the cloudflared child process.
|
|
31
|
+
*/
|
|
32
|
+
setProcess(process: ChildProcess): void;
|
|
33
|
+
/**
|
|
34
|
+
* Stores the auto-cleanup timeout ID.
|
|
35
|
+
*/
|
|
36
|
+
setTimeout(timeoutId: ReturnType<typeof setTimeout>): void;
|
|
37
|
+
/**
|
|
38
|
+
* Clears the auto-cleanup timeout if set.
|
|
39
|
+
*/
|
|
40
|
+
clearTimeout(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Increments the connection count and returns the new value.
|
|
43
|
+
*/
|
|
44
|
+
incrementConnection(): number;
|
|
45
|
+
/**
|
|
46
|
+
* Checks if a tunnel is currently active.
|
|
47
|
+
*/
|
|
48
|
+
hasTunnel(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if the cloudflared process is running.
|
|
51
|
+
*/
|
|
52
|
+
hasProcess(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the tunnel duration in seconds.
|
|
55
|
+
*/
|
|
56
|
+
getDurationSeconds(): number;
|
|
57
|
+
/**
|
|
58
|
+
* Increments the network issue counter.
|
|
59
|
+
*/
|
|
60
|
+
incrementNetworkIssue(): number;
|
|
61
|
+
/**
|
|
62
|
+
* Resets the network issue counter.
|
|
63
|
+
*/
|
|
64
|
+
resetNetworkIssues(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Determines if a network warning should be shown.
|
|
67
|
+
*/
|
|
68
|
+
shouldShowNetworkWarning(threshold: number, cooldown: number): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Sets whether a network warning has been shown.
|
|
71
|
+
*/
|
|
72
|
+
setNetworkWarningShown(value: boolean): void;
|
|
73
|
+
/**
|
|
74
|
+
* Resets all state to initial values.
|
|
75
|
+
*/
|
|
76
|
+
reset(): void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Singleton instance
|
|
80
|
+
*/
|
|
81
|
+
export declare const state: TunnelState;
|
|
82
|
+
export {};
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application State Manager
|
|
3
|
+
*
|
|
4
|
+
* Singleton class that manages all runtime state for the tunnel.
|
|
5
|
+
*/
|
|
6
|
+
class TunnelState {
|
|
7
|
+
tunnelId = null;
|
|
8
|
+
subdomain = null;
|
|
9
|
+
port = null;
|
|
10
|
+
backendUrl = null;
|
|
11
|
+
tunnelProcess = null;
|
|
12
|
+
timeoutId = null;
|
|
13
|
+
connectionCount = 0;
|
|
14
|
+
startTime = null;
|
|
15
|
+
updateInfo = null;
|
|
16
|
+
// Network issue tracking
|
|
17
|
+
networkIssueCount = 0;
|
|
18
|
+
lastNetworkWarningTime = 0;
|
|
19
|
+
networkWarningShown = false;
|
|
20
|
+
/**
|
|
21
|
+
* Sets the tunnel connection information.
|
|
22
|
+
*/
|
|
23
|
+
setTunnel(tunnelId, subdomain, port, backendUrl = null) {
|
|
24
|
+
this.tunnelId = tunnelId;
|
|
25
|
+
this.subdomain = subdomain;
|
|
26
|
+
this.port = port;
|
|
27
|
+
this.backendUrl = backendUrl;
|
|
28
|
+
if (!this.startTime) {
|
|
29
|
+
this.startTime = Date.now();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Stores version update information.
|
|
34
|
+
*/
|
|
35
|
+
setUpdateInfo(updateInfo) {
|
|
36
|
+
this.updateInfo = updateInfo;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Stores reference to the cloudflared child process.
|
|
40
|
+
*/
|
|
41
|
+
setProcess(process) {
|
|
42
|
+
this.tunnelProcess = process;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Stores the auto-cleanup timeout ID.
|
|
46
|
+
*/
|
|
47
|
+
setTimeout(timeoutId) {
|
|
48
|
+
this.timeoutId = timeoutId;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Clears the auto-cleanup timeout if set.
|
|
52
|
+
*/
|
|
53
|
+
clearTimeout() {
|
|
54
|
+
if (this.timeoutId) {
|
|
55
|
+
clearTimeout(this.timeoutId);
|
|
56
|
+
this.timeoutId = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Increments the connection count and returns the new value.
|
|
61
|
+
*/
|
|
62
|
+
incrementConnection() {
|
|
63
|
+
this.connectionCount++;
|
|
64
|
+
return this.connectionCount;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Checks if a tunnel is currently active.
|
|
68
|
+
*/
|
|
69
|
+
hasTunnel() {
|
|
70
|
+
return this.tunnelId !== null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Checks if the cloudflared process is running.
|
|
74
|
+
*/
|
|
75
|
+
hasProcess() {
|
|
76
|
+
return this.tunnelProcess !== null && !this.tunnelProcess.killed;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Gets the tunnel duration in seconds.
|
|
80
|
+
*/
|
|
81
|
+
getDurationSeconds() {
|
|
82
|
+
if (!this.startTime)
|
|
83
|
+
return 0;
|
|
84
|
+
return (Date.now() - this.startTime) / 1000;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Increments the network issue counter.
|
|
88
|
+
*/
|
|
89
|
+
incrementNetworkIssue() {
|
|
90
|
+
this.networkIssueCount++;
|
|
91
|
+
return this.networkIssueCount;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Resets the network issue counter.
|
|
95
|
+
*/
|
|
96
|
+
resetNetworkIssues() {
|
|
97
|
+
this.networkIssueCount = 0;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Determines if a network warning should be shown.
|
|
101
|
+
*/
|
|
102
|
+
shouldShowNetworkWarning(threshold, cooldown) {
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
if (this.networkIssueCount >= threshold &&
|
|
105
|
+
now - this.lastNetworkWarningTime > cooldown) {
|
|
106
|
+
this.lastNetworkWarningTime = now;
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Sets whether a network warning has been shown.
|
|
113
|
+
*/
|
|
114
|
+
setNetworkWarningShown(value) {
|
|
115
|
+
this.networkWarningShown = value;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Resets all state to initial values.
|
|
119
|
+
*/
|
|
120
|
+
reset() {
|
|
121
|
+
this.clearTimeout();
|
|
122
|
+
this.tunnelId = null;
|
|
123
|
+
this.subdomain = null;
|
|
124
|
+
this.port = null;
|
|
125
|
+
this.backendUrl = null;
|
|
126
|
+
this.tunnelProcess = null;
|
|
127
|
+
this.connectionCount = 0;
|
|
128
|
+
this.startTime = null;
|
|
129
|
+
this.updateInfo = null;
|
|
130
|
+
this.networkIssueCount = 0;
|
|
131
|
+
this.lastNetworkWarningTime = 0;
|
|
132
|
+
this.networkWarningShown = false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Singleton instance
|
|
137
|
+
*/
|
|
138
|
+
export const state = new TunnelState();
|
|
139
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/dist/tunnel.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TunnelConfig, ShutdownReason } from './types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tunnel Orchestrator
|
|
4
|
+
*
|
|
5
|
+
* Main controller for the entire tunnel lifecycle.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TunnelOrchestrator {
|
|
8
|
+
/**
|
|
9
|
+
* Starts the tunnel creation process.
|
|
10
|
+
*/
|
|
11
|
+
static start(config: TunnelConfig): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Gracefully shuts down the tunnel.
|
|
14
|
+
*/
|
|
15
|
+
static cleanup(reason?: ShutdownReason): Promise<void>;
|
|
16
|
+
}
|
package/dist/tunnel.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { CONFIG, PATHS, TUNNEL_TIMEOUT_MS } from './config.js';
|
|
5
|
+
import { state } from './state.js';
|
|
6
|
+
import { BinaryManager } from './binary.js';
|
|
7
|
+
import { ensureCloudflared } from './bin-manager.js';
|
|
8
|
+
import { APIClient } from './api.js';
|
|
9
|
+
import { VersionManager } from './version.js';
|
|
10
|
+
import { UI } from './ui.js';
|
|
11
|
+
import { analytics } from './analytics.js';
|
|
12
|
+
import { lang } from './lang.js';
|
|
13
|
+
/**
|
|
14
|
+
* Tunnel Orchestrator
|
|
15
|
+
*
|
|
16
|
+
* Main controller for the entire tunnel lifecycle.
|
|
17
|
+
*/
|
|
18
|
+
export class TunnelOrchestrator {
|
|
19
|
+
/**
|
|
20
|
+
* Starts the tunnel creation process.
|
|
21
|
+
*/
|
|
22
|
+
static async start(config) {
|
|
23
|
+
state.setTunnel(null, config.subdomain, config.port, config.backendUrl);
|
|
24
|
+
await analytics.initialize();
|
|
25
|
+
analytics.trackCliStart(config.port, config.subdomain, CONFIG.CURRENT_VERSION);
|
|
26
|
+
UI.displayStartupBanner(config.port);
|
|
27
|
+
const updateInfo = await VersionManager.checkForUpdates();
|
|
28
|
+
state.setUpdateInfo(updateInfo);
|
|
29
|
+
// Check if binary exists, download if missing
|
|
30
|
+
if (!fs.existsSync(PATHS.BIN_PATH)) {
|
|
31
|
+
console.log(chalk.yellow('\n📦 Cloudflared binary not found. Downloading...\n'));
|
|
32
|
+
try {
|
|
33
|
+
await ensureCloudflared();
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
analytics.trackTunnelError('binary_download_failed', error.message);
|
|
37
|
+
console.error(chalk.red(`\n❌ Failed to download cloudflared: ${error.message}`));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!BinaryManager.validate(PATHS.BIN_PATH)) {
|
|
42
|
+
analytics.trackTunnelError('binary_missing', 'Cloudflared binary not found');
|
|
43
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const spinner = ora(lang.t('creatingTunnel', { port: config.port })).start();
|
|
47
|
+
try {
|
|
48
|
+
const tunnel = await APIClient.createTunnel(config.subdomain, config.backendUrl);
|
|
49
|
+
state.setTunnel(tunnel.tunnelId, config.subdomain, config.port, config.backendUrl);
|
|
50
|
+
analytics.trackTunnelCreated(config.subdomain, config.port);
|
|
51
|
+
spinner.stop();
|
|
52
|
+
console.log(chalk.green(` ${lang.t('tunnelLive')}`));
|
|
53
|
+
UI.displayTunnelSuccess(tunnel.url, config.port, updateInfo);
|
|
54
|
+
const childProcess = BinaryManager.spawn(PATHS.BIN_PATH, tunnel.tunnelToken, config.port);
|
|
55
|
+
state.setProcess(childProcess);
|
|
56
|
+
BinaryManager.attachHandlers(childProcess, spinner);
|
|
57
|
+
const timeoutId = setTimeout(() => {
|
|
58
|
+
UI.displayTimeoutWarning();
|
|
59
|
+
this.cleanup('timeout');
|
|
60
|
+
}, TUNNEL_TIMEOUT_MS);
|
|
61
|
+
state.setTimeout(timeoutId);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const err = error;
|
|
65
|
+
const errorType = err.message.includes('already taken')
|
|
66
|
+
? 'subdomain_taken'
|
|
67
|
+
: 'tunnel_creation_failed';
|
|
68
|
+
analytics.trackTunnelError(errorType, err.message);
|
|
69
|
+
UI.displayError(err, spinner);
|
|
70
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Gracefully shuts down the tunnel.
|
|
76
|
+
*/
|
|
77
|
+
static async cleanup(reason = 'manual') {
|
|
78
|
+
state.clearTimeout();
|
|
79
|
+
if (!state.hasTunnel()) {
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
UI.displayCleanupStart();
|
|
83
|
+
const duration = state.getDurationSeconds();
|
|
84
|
+
analytics.trackTunnelShutdown(reason, duration);
|
|
85
|
+
try {
|
|
86
|
+
if (state.hasProcess() && state.tunnelProcess) {
|
|
87
|
+
state.tunnelProcess.kill();
|
|
88
|
+
}
|
|
89
|
+
if (state.subdomain && state.tunnelId) {
|
|
90
|
+
await APIClient.deleteTunnel(state.subdomain, state.tunnelId, state.backendUrl);
|
|
91
|
+
}
|
|
92
|
+
UI.displayCleanupSuccess();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
UI.displayCleanupError();
|
|
96
|
+
}
|
|
97
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=tunnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../src/tunnel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics type definitions
|
|
3
|
+
*
|
|
4
|
+
* These types define the structure of analytics events
|
|
5
|
+
* and tracking data.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Base analytics event
|
|
9
|
+
*/
|
|
10
|
+
export interface AnalyticsEvent {
|
|
11
|
+
/** Event name */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Event parameters */
|
|
14
|
+
params: Record<string, string | number | boolean>;
|
|
15
|
+
/** Timestamp when event occurred */
|
|
16
|
+
timestamp?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* CLI start event parameters
|
|
20
|
+
*/
|
|
21
|
+
export interface CliStartEventParams {
|
|
22
|
+
/** Port being tunneled */
|
|
23
|
+
port: string;
|
|
24
|
+
/** Whether a custom subdomain was provided */
|
|
25
|
+
has_custom_subdomain: boolean;
|
|
26
|
+
/** CLI version */
|
|
27
|
+
cli_version: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Tunnel created event parameters
|
|
31
|
+
*/
|
|
32
|
+
export interface TunnelCreatedEventParams {
|
|
33
|
+
/** Type of subdomain (random or custom) */
|
|
34
|
+
subdomain_type: 'random' | 'custom';
|
|
35
|
+
/** Port being tunneled */
|
|
36
|
+
port: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Tunnel error event parameters
|
|
40
|
+
*/
|
|
41
|
+
export interface TunnelErrorEventParams {
|
|
42
|
+
/** Type of error */
|
|
43
|
+
error_type: string;
|
|
44
|
+
/** Error message (truncated) */
|
|
45
|
+
error_message: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Tunnel shutdown event parameters
|
|
49
|
+
*/
|
|
50
|
+
export interface TunnelShutdownEventParams {
|
|
51
|
+
/** Reason for shutdown */
|
|
52
|
+
shutdown_reason: 'manual' | 'timeout' | 'error';
|
|
53
|
+
/** Duration in seconds */
|
|
54
|
+
duration_seconds: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Update available event parameters
|
|
58
|
+
*/
|
|
59
|
+
export interface UpdateAvailableEventParams {
|
|
60
|
+
/** Current version */
|
|
61
|
+
current_version: string;
|
|
62
|
+
/** Latest version */
|
|
63
|
+
latest_version: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* System information for analytics context
|
|
67
|
+
*/
|
|
68
|
+
export interface SystemInfo {
|
|
69
|
+
/** Operating system platform */
|
|
70
|
+
os_platform: string;
|
|
71
|
+
/** OS version */
|
|
72
|
+
os_version: string;
|
|
73
|
+
/** CPU architecture */
|
|
74
|
+
os_arch: string;
|
|
75
|
+
/** Node.js version */
|
|
76
|
+
node_version: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* GA4 Measurement Protocol payload
|
|
80
|
+
*/
|
|
81
|
+
export interface GA4Payload {
|
|
82
|
+
/** Client ID (user identifier) */
|
|
83
|
+
client_id: string;
|
|
84
|
+
/** Array of events */
|
|
85
|
+
events: Array<{
|
|
86
|
+
/** Event name */
|
|
87
|
+
name: string;
|
|
88
|
+
/** Event parameters */
|
|
89
|
+
params: Record<string, string | number | boolean>;
|
|
90
|
+
}>;
|
|
91
|
+
}
|