pinggy 0.4.5 → 0.4.6
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/dist/{chunk-HUN2MRZO.js → chunk-3RTRUYNW.js} +3 -1
- package/dist/{chunk-MBN3YBO4.js → chunk-STEISST3.js} +203 -41
- package/dist/index.cjs +339 -90
- package/dist/index.d.cts +20 -11
- package/dist/index.d.ts +20 -11
- package/dist/index.js +10 -7
- package/dist/{main-2RDHMQT7.js → main-XKFFUSKJ.js} +130 -46
- package/dist/workers/file_serve_worker.js +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -116,6 +116,11 @@ var init_printer = __esm({
|
|
|
116
116
|
const def = this.errorDefinitions.find((d) => d.match(err));
|
|
117
117
|
const msg = def.message(err);
|
|
118
118
|
console.error(import_picocolors2.default.red(import_picocolors2.default.bold("\u2716 Error:")), import_picocolors2.default.red(msg));
|
|
119
|
+
}
|
|
120
|
+
static fatal(err) {
|
|
121
|
+
const def = this.errorDefinitions.find((d) => d.match(err));
|
|
122
|
+
const msg = def.message(err);
|
|
123
|
+
console.error(import_picocolors2.default.red(import_picocolors2.default.bold("\u2716 Fatal Error:")), import_picocolors2.default.red(msg));
|
|
119
124
|
process.exit(1);
|
|
120
125
|
}
|
|
121
126
|
static red(message) {
|
|
@@ -254,7 +259,9 @@ function enablePackageLogging(opts) {
|
|
|
254
259
|
return applyLoggingConfig(opts ?? {});
|
|
255
260
|
}
|
|
256
261
|
function enableLoggingByLogLevelInSdk(loglevel, logFilePath) {
|
|
257
|
-
if (!loglevel)
|
|
262
|
+
if (!loglevel) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
258
265
|
const l = loglevel.toUpperCase();
|
|
259
266
|
if (loglevel === "DEBUG") {
|
|
260
267
|
import_pinggy.pinggy.setDebugLogging(true, import_pinggy.LogLevel.DEBUG, logFilePath);
|
|
@@ -430,7 +437,9 @@ var init_TunnelManager = __esm({
|
|
|
430
437
|
*/
|
|
431
438
|
async startTunnel(tunnelId) {
|
|
432
439
|
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
433
|
-
if (!managed)
|
|
440
|
+
if (!managed) {
|
|
441
|
+
throw new Error(`Tunnel with id "${tunnelId}" not found`);
|
|
442
|
+
}
|
|
434
443
|
logger.info("Starting tunnel", { tunnelId });
|
|
435
444
|
let urls;
|
|
436
445
|
try {
|
|
@@ -478,7 +487,9 @@ var init_TunnelManager = __esm({
|
|
|
478
487
|
*/
|
|
479
488
|
stopTunnel(tunnelId) {
|
|
480
489
|
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
481
|
-
if (!managed)
|
|
490
|
+
if (!managed) {
|
|
491
|
+
throw new Error(`Tunnel "${tunnelId}" not found`);
|
|
492
|
+
}
|
|
482
493
|
logger.info("Stopping tunnel", { tunnelId, configId: managed.configId });
|
|
483
494
|
try {
|
|
484
495
|
managed.instance.stop();
|
|
@@ -659,12 +670,16 @@ var init_TunnelManager = __esm({
|
|
|
659
670
|
getTunnelInstance(configId, tunnelId) {
|
|
660
671
|
if (configId) {
|
|
661
672
|
const managed = this.tunnelsByConfigId.get(configId);
|
|
662
|
-
if (!managed)
|
|
673
|
+
if (!managed) {
|
|
674
|
+
throw new Error(`Tunnel "${configId}" not found`);
|
|
675
|
+
}
|
|
663
676
|
return managed.instance;
|
|
664
677
|
}
|
|
665
678
|
if (tunnelId) {
|
|
666
679
|
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
667
|
-
if (!managed)
|
|
680
|
+
if (!managed) {
|
|
681
|
+
throw new Error(`Tunnel "${tunnelId}" not found`);
|
|
682
|
+
}
|
|
668
683
|
return managed.instance;
|
|
669
684
|
}
|
|
670
685
|
throw new Error(`Either configId or tunnelId must be provided`);
|
|
@@ -843,12 +858,16 @@ var init_TunnelManager = __esm({
|
|
|
843
858
|
getManagedTunnel(configId, tunnelId) {
|
|
844
859
|
if (configId) {
|
|
845
860
|
const managed = this.tunnelsByConfigId.get(configId);
|
|
846
|
-
if (!managed)
|
|
861
|
+
if (!managed) {
|
|
862
|
+
throw new Error(`Tunnel "${configId}" not found`);
|
|
863
|
+
}
|
|
847
864
|
return managed;
|
|
848
865
|
}
|
|
849
866
|
if (tunnelId) {
|
|
850
867
|
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
851
|
-
if (!managed)
|
|
868
|
+
if (!managed) {
|
|
869
|
+
throw new Error(`Tunnel "${tunnelId}" not found`);
|
|
870
|
+
}
|
|
852
871
|
return managed;
|
|
853
872
|
}
|
|
854
873
|
throw new Error(`Either configId or tunnelId must be provided`);
|
|
@@ -1237,7 +1256,9 @@ var init_TunnelManager = __esm({
|
|
|
1237
1256
|
notifyPollingErrorListeners(tunnelId, errorMsg) {
|
|
1238
1257
|
try {
|
|
1239
1258
|
const listeners = this.tunnelPollingErrorListeners.get(tunnelId);
|
|
1240
|
-
if (!listeners)
|
|
1259
|
+
if (!listeners) {
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1241
1262
|
for (const [id, listener] of listeners) {
|
|
1242
1263
|
try {
|
|
1243
1264
|
listener(tunnelId, errorMsg);
|
|
@@ -1252,7 +1273,9 @@ var init_TunnelManager = __esm({
|
|
|
1252
1273
|
notifyErrorListeners(tunnelId, errorMsg, isFatal) {
|
|
1253
1274
|
try {
|
|
1254
1275
|
const listeners = this.tunnelErrorListeners.get(tunnelId);
|
|
1255
|
-
if (!listeners)
|
|
1276
|
+
if (!listeners) {
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1256
1279
|
for (const [id, listener] of listeners) {
|
|
1257
1280
|
try {
|
|
1258
1281
|
listener(tunnelId, errorMsg, isFatal);
|
|
@@ -1301,7 +1324,9 @@ var init_TunnelManager = __esm({
|
|
|
1301
1324
|
managedTunnel.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1302
1325
|
}
|
|
1303
1326
|
const listeners = this.tunnelDisconnectListeners.get(tunnelId);
|
|
1304
|
-
if (!listeners)
|
|
1327
|
+
if (!listeners) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1305
1330
|
for (const [id, listener] of listeners) {
|
|
1306
1331
|
try {
|
|
1307
1332
|
listener(tunnelId, error, messages);
|
|
@@ -1329,7 +1354,9 @@ var init_TunnelManager = __esm({
|
|
|
1329
1354
|
try {
|
|
1330
1355
|
logger.info("Tunnel will reconnect", { tunnelId, error, messages });
|
|
1331
1356
|
const listeners = this.tunnelWillReconnectListeners.get(tunnelId);
|
|
1332
|
-
if (!listeners)
|
|
1357
|
+
if (!listeners) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1333
1360
|
for (const [id, listener] of listeners) {
|
|
1334
1361
|
try {
|
|
1335
1362
|
listener(tunnelId, error, messages);
|
|
@@ -1357,7 +1384,9 @@ var init_TunnelManager = __esm({
|
|
|
1357
1384
|
try {
|
|
1358
1385
|
logger.info("Tunnel reconnecting", { tunnelId, retryCnt });
|
|
1359
1386
|
const listeners = this.tunnelReconnectingListeners.get(tunnelId);
|
|
1360
|
-
if (!listeners)
|
|
1387
|
+
if (!listeners) {
|
|
1388
|
+
return;
|
|
1389
|
+
}
|
|
1361
1390
|
for (const [id, listener] of listeners) {
|
|
1362
1391
|
try {
|
|
1363
1392
|
listener(tunnelId, retryCnt);
|
|
@@ -1435,7 +1464,9 @@ var init_TunnelManager = __esm({
|
|
|
1435
1464
|
managedTunnel.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1436
1465
|
}
|
|
1437
1466
|
const listeners = this.tunnelReconnectionFailedListeners.get(tunnelId);
|
|
1438
|
-
if (!listeners)
|
|
1467
|
+
if (!listeners) {
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1439
1470
|
for (const [id, listener] of listeners) {
|
|
1440
1471
|
try {
|
|
1441
1472
|
listener(tunnelId, retryCnt);
|
|
@@ -1459,7 +1490,9 @@ var init_TunnelManager = __esm({
|
|
|
1459
1490
|
try {
|
|
1460
1491
|
logger.debug("Error in Tunnel Worker", { tunnelId, errorMessage: error.message });
|
|
1461
1492
|
const listeners = this.tunnelWorkerErrorListeners.get(tunnelId);
|
|
1462
|
-
if (!listeners)
|
|
1493
|
+
if (!listeners) {
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1463
1496
|
for (const [id, listener] of listeners) {
|
|
1464
1497
|
try {
|
|
1465
1498
|
listener(tunnelId, error);
|
|
@@ -1945,6 +1978,7 @@ var init_handler = __esm({
|
|
|
1945
1978
|
"use strict";
|
|
1946
1979
|
init_cjs_shims();
|
|
1947
1980
|
init_types();
|
|
1981
|
+
init_logger();
|
|
1948
1982
|
init_TunnelManager();
|
|
1949
1983
|
init_remote_schema();
|
|
1950
1984
|
TunnelOperations = class {
|
|
@@ -1967,6 +2001,26 @@ var init_handler = __esm({
|
|
|
1967
2001
|
}
|
|
1968
2002
|
return status;
|
|
1969
2003
|
}
|
|
2004
|
+
// --- Placeholder response ---
|
|
2005
|
+
buildPendingTunnelResponse(tunnelid, tunnelConfig, configid, tunnelName, serve) {
|
|
2006
|
+
return {
|
|
2007
|
+
tunnelid,
|
|
2008
|
+
remoteurls: [],
|
|
2009
|
+
tunnelconfig: pinggyOptionsToTunnelConfig(tunnelConfig, configid, tunnelName, false, void 0, serve),
|
|
2010
|
+
status: this.buildStatus(tunnelid, "starting" /* Starting */, "" /* NoError */),
|
|
2011
|
+
stats: newStats()
|
|
2012
|
+
};
|
|
2013
|
+
}
|
|
2014
|
+
buildPendingTunnelResponseV2(tunnelid, tunnelConfig, configFromCli, configid, tunnelName, serve) {
|
|
2015
|
+
return {
|
|
2016
|
+
tunnelid,
|
|
2017
|
+
remoteurls: [],
|
|
2018
|
+
tunnelconfig: pinggyOptionsToTunnelConfigV1(tunnelConfig, configFromCli),
|
|
2019
|
+
status: this.buildStatus(tunnelid, "starting" /* Starting */, "" /* NoError */),
|
|
2020
|
+
stats: newStats(),
|
|
2021
|
+
greetmsg: ""
|
|
2022
|
+
};
|
|
2023
|
+
}
|
|
1970
2024
|
// --- Helper to construct TunnelResponse ---
|
|
1971
2025
|
async buildTunnelResponse(tunnelid, tunnelConfig, configid, tunnelName, serve) {
|
|
1972
2026
|
const [status, stats, tlsInfo, greetMsg, remoteurls] = await Promise.all([
|
|
@@ -2007,10 +2061,10 @@ var init_handler = __esm({
|
|
|
2007
2061
|
});
|
|
2008
2062
|
}
|
|
2009
2063
|
// --- Operations ---
|
|
2010
|
-
async handleStart(config) {
|
|
2064
|
+
async handleStart(config, noWait = false) {
|
|
2011
2065
|
try {
|
|
2012
2066
|
const opts = tunnelConfigToPinggyOptions(config);
|
|
2013
|
-
const
|
|
2067
|
+
const managed = await this.tunnelManager.createTunnel({
|
|
2014
2068
|
...opts,
|
|
2015
2069
|
configId: config.configid,
|
|
2016
2070
|
name: config.configname,
|
|
@@ -2018,36 +2072,52 @@ var init_handler = __esm({
|
|
|
2018
2072
|
serve: config.serve
|
|
2019
2073
|
}
|
|
2020
2074
|
});
|
|
2021
|
-
|
|
2075
|
+
const { tunnelid, tunnelName, serve, tunnelConfig } = managed;
|
|
2076
|
+
const startPromise = this.tunnelManager.startTunnel(tunnelid);
|
|
2077
|
+
if (noWait) {
|
|
2078
|
+
startPromise.catch((err) => {
|
|
2079
|
+
logger.error("No-wait startTunnel failed", { tunnelid, err: String(err) });
|
|
2080
|
+
});
|
|
2081
|
+
return this.buildPendingTunnelResponse(tunnelid, tunnelConfig, config.configid, tunnelName, serve);
|
|
2082
|
+
}
|
|
2083
|
+
await startPromise;
|
|
2022
2084
|
const tunnelPconfig = await this.tunnelManager.getTunnelConfig("", tunnelid);
|
|
2023
|
-
|
|
2024
|
-
return resp;
|
|
2085
|
+
return this.buildTunnelResponse(tunnelid, tunnelPconfig, config.configid, tunnelName, serve);
|
|
2025
2086
|
} catch (err) {
|
|
2026
2087
|
return this.error(ErrorCode.ErrorStartingTunnel, err, "Unknown error occurred while starting tunnel");
|
|
2027
2088
|
}
|
|
2028
2089
|
}
|
|
2029
|
-
async handleStartV2(config) {
|
|
2090
|
+
async handleStartV2(config, noWait = false) {
|
|
2030
2091
|
try {
|
|
2031
|
-
const
|
|
2092
|
+
const managed = await this.tunnelManager.createTunnel(config);
|
|
2093
|
+
const { tunnelid, serve, tunnelConfig } = managed;
|
|
2032
2094
|
await this.tunnelManager.startTunnel(tunnelid);
|
|
2033
2095
|
const tunnelPconfig = await this.tunnelManager.getTunnelConfig("", tunnelid);
|
|
2034
|
-
|
|
2035
|
-
return resp;
|
|
2096
|
+
return this.buildTunnelResponseV2(tunnelid, tunnelPconfig, config, config.configId, config.name, config.serve);
|
|
2036
2097
|
} catch (err) {
|
|
2037
2098
|
return this.error(ErrorCode.ErrorStartingTunnel, err, "Unknown error occurred while starting tunnel");
|
|
2038
2099
|
}
|
|
2039
2100
|
}
|
|
2040
|
-
async handleUpdateConfig(config) {
|
|
2101
|
+
async handleUpdateConfig(config, noWait = false) {
|
|
2041
2102
|
try {
|
|
2042
2103
|
const opts = tunnelConfigToPinggyOptions(config);
|
|
2043
|
-
const
|
|
2104
|
+
const updateOpts = {
|
|
2044
2105
|
...opts,
|
|
2045
2106
|
configId: config.configid,
|
|
2046
2107
|
name: config.configname,
|
|
2047
2108
|
optional: {
|
|
2048
2109
|
serve: config.serve
|
|
2049
2110
|
}
|
|
2050
|
-
}
|
|
2111
|
+
};
|
|
2112
|
+
if (noWait) {
|
|
2113
|
+
const existing = this.tunnelManager.getManagedTunnel(config.configid);
|
|
2114
|
+
if (!existing.tunnelConfig) throw new Error("Invalid tunnel state before configuration update");
|
|
2115
|
+
this.tunnelManager.updateConfig(updateOpts).catch((err) => {
|
|
2116
|
+
logger.error("No-wait updateConfig failed", { configid: config.configid, err: String(err) });
|
|
2117
|
+
});
|
|
2118
|
+
return this.buildPendingTunnelResponse(existing.tunnelid, existing.tunnelConfig, config.configid, existing.tunnelName, existing.serve);
|
|
2119
|
+
}
|
|
2120
|
+
const tunnel = await this.tunnelManager.updateConfig(updateOpts);
|
|
2051
2121
|
if (!tunnel.instance || !tunnel.tunnelConfig)
|
|
2052
2122
|
throw new Error("Invalid tunnel state after configuration update");
|
|
2053
2123
|
return this.buildTunnelResponse(tunnel.tunnelid, tunnel.tunnelConfig, config.configid, tunnel.tunnelName, tunnel.serve);
|
|
@@ -2055,8 +2125,17 @@ var init_handler = __esm({
|
|
|
2055
2125
|
return this.error(ErrorCode.InternalServerError, err, "Failed to update tunnel configuration");
|
|
2056
2126
|
}
|
|
2057
2127
|
}
|
|
2058
|
-
async handleUpdateConfigV2(config) {
|
|
2128
|
+
async handleUpdateConfigV2(config, noWait = false) {
|
|
2059
2129
|
try {
|
|
2130
|
+
if (noWait) {
|
|
2131
|
+
const existing = this.tunnelManager.getManagedTunnel(config.configId);
|
|
2132
|
+
console.log(existing);
|
|
2133
|
+
if (!existing.tunnelConfig) throw new Error("Invalid tunnel state before configuration update");
|
|
2134
|
+
this.tunnelManager.updateConfig(config).catch((err) => {
|
|
2135
|
+
logger.error("No-wait updateConfigV2 failed", { configId: config.configId, err: String(err) });
|
|
2136
|
+
});
|
|
2137
|
+
return this.buildPendingTunnelResponseV2(existing.tunnelid, existing.tunnelConfig, config, config.configId, existing.tunnelName, existing.serve);
|
|
2138
|
+
}
|
|
2060
2139
|
const tunnel = await this.tunnelManager.updateConfig(config);
|
|
2061
2140
|
if (!tunnel.instance || !tunnel.tunnelConfig)
|
|
2062
2141
|
throw new Error("Invalid tunnel state after configuration update");
|
|
@@ -2143,8 +2222,16 @@ var init_handler = __esm({
|
|
|
2143
2222
|
return this.error(ErrorCode.TunnelNotFound, err, "Failed to get tunnel information");
|
|
2144
2223
|
}
|
|
2145
2224
|
}
|
|
2146
|
-
async handleRestart(tunnelid) {
|
|
2225
|
+
async handleRestart(tunnelid, noWait = false) {
|
|
2147
2226
|
try {
|
|
2227
|
+
if (noWait) {
|
|
2228
|
+
const managed2 = this.tunnelManager.getManagedTunnel("", tunnelid);
|
|
2229
|
+
if (!managed2?.tunnelConfig) throw new Error(`Tunnel config for ID "${tunnelid}" not found`);
|
|
2230
|
+
this.tunnelManager.restartTunnel(tunnelid).catch((err) => {
|
|
2231
|
+
logger.error("No-wait restartTunnel failed", { tunnelid, err: String(err) });
|
|
2232
|
+
});
|
|
2233
|
+
return this.buildPendingTunnelResponse(tunnelid, managed2.tunnelConfig, managed2.configId, managed2.tunnelName, managed2.serve);
|
|
2234
|
+
}
|
|
2148
2235
|
await this.tunnelManager.restartTunnel(tunnelid);
|
|
2149
2236
|
const managed = this.tunnelManager.getManagedTunnel("", tunnelid);
|
|
2150
2237
|
if (!managed?.tunnelConfig) throw new Error(`Tunnel config for ID "${tunnelid}" not found`);
|
|
@@ -2463,7 +2550,7 @@ var init_websocket_handlers = __esm({
|
|
|
2463
2550
|
const dc = StartSchema.parse(raw);
|
|
2464
2551
|
queuedConfig = dc.tunnelConfig;
|
|
2465
2552
|
remoteManagementWebSocketPrinter.queueStart(dc.tunnelConfig);
|
|
2466
|
-
const result = await this.tunnelHandler.handleStart(dc.tunnelConfig);
|
|
2553
|
+
const result = await this.tunnelHandler.handleStart(dc.tunnelConfig, true);
|
|
2467
2554
|
remoteManagementWebSocketPrinter.handleStartResult(dc.tunnelConfig, result);
|
|
2468
2555
|
return this.wrapResponse(result, req);
|
|
2469
2556
|
} catch (e) {
|
|
@@ -2484,7 +2571,7 @@ var init_websocket_handlers = __esm({
|
|
|
2484
2571
|
const dc = StartV2Schema.parse(raw);
|
|
2485
2572
|
queuedConfig = dc.tunnelConfig;
|
|
2486
2573
|
remoteManagementWebSocketPrinter.queueStart(dc.tunnelConfig);
|
|
2487
|
-
const result = await this.tunnelHandler.handleStartV2(dc.tunnelConfig);
|
|
2574
|
+
const result = await this.tunnelHandler.handleStartV2(dc.tunnelConfig, true);
|
|
2488
2575
|
remoteManagementWebSocketPrinter.handleStartResult(dc.tunnelConfig, result);
|
|
2489
2576
|
return this.wrapResponse(result, req);
|
|
2490
2577
|
} catch (e) {
|
|
@@ -2533,7 +2620,7 @@ var init_websocket_handlers = __esm({
|
|
|
2533
2620
|
try {
|
|
2534
2621
|
const dc = RestartSchema.parse(raw);
|
|
2535
2622
|
remoteManagementWebSocketPrinter.printRestartRequested(dc.tunnelID);
|
|
2536
|
-
const result = await this.tunnelHandler.handleRestart(dc.tunnelID);
|
|
2623
|
+
const result = await this.tunnelHandler.handleRestart(dc.tunnelID, true);
|
|
2537
2624
|
remoteManagementWebSocketPrinter.handleRestartResult(dc.tunnelID, result);
|
|
2538
2625
|
return this.wrapResponse(result, req);
|
|
2539
2626
|
} catch (e) {
|
|
@@ -2548,7 +2635,7 @@ var init_websocket_handlers = __esm({
|
|
|
2548
2635
|
async handleUpdateConfigReq(req, raw) {
|
|
2549
2636
|
try {
|
|
2550
2637
|
const dc = UpdateConfigSchema.parse(raw);
|
|
2551
|
-
const result = await this.tunnelHandler.handleUpdateConfig(dc.tunnelConfig);
|
|
2638
|
+
const result = await this.tunnelHandler.handleUpdateConfig(dc.tunnelConfig, true);
|
|
2552
2639
|
return this.wrapResponse(result, req);
|
|
2553
2640
|
} catch (e) {
|
|
2554
2641
|
if (e instanceof import_zod2.default.ZodError) {
|
|
@@ -2562,7 +2649,7 @@ var init_websocket_handlers = __esm({
|
|
|
2562
2649
|
async handleUpdateConfigV2Req(req, raw) {
|
|
2563
2650
|
try {
|
|
2564
2651
|
const dc = UpdateConfigV2Schema.parse(raw);
|
|
2565
|
-
const result = await this.tunnelHandler.handleUpdateConfigV2(dc.tunnelConfig);
|
|
2652
|
+
const result = await this.tunnelHandler.handleUpdateConfigV2(dc.tunnelConfig, true);
|
|
2566
2653
|
return this.wrapResponse(result, req);
|
|
2567
2654
|
} catch (e) {
|
|
2568
2655
|
if (e instanceof import_zod2.default.ZodError) {
|
|
@@ -2758,9 +2845,14 @@ async function initiateRemoteManagement(remoteManagementConfig) {
|
|
|
2758
2845
|
try {
|
|
2759
2846
|
await handleWebSocketConnection(wsUrl, wsHost, remoteManagementConfig.apiKey);
|
|
2760
2847
|
} catch (error) {
|
|
2848
|
+
if (error instanceof RemoteManagementUnauthorizedError) {
|
|
2849
|
+
throw error;
|
|
2850
|
+
}
|
|
2761
2851
|
logger.warn("Remote management connection error", { error: String(error) });
|
|
2762
2852
|
}
|
|
2763
|
-
if (_stopRequested)
|
|
2853
|
+
if (_stopRequested) {
|
|
2854
|
+
break;
|
|
2855
|
+
}
|
|
2764
2856
|
printer_default.warn(`Remote management disconnected. Reconnecting in ${RECONNECT_SLEEP_MS / 1e3} seconds...`);
|
|
2765
2857
|
logger.info("Reconnecting to remote management after disconnect");
|
|
2766
2858
|
await sleep(RECONNECT_SLEEP_MS);
|
|
@@ -2769,22 +2861,34 @@ async function initiateRemoteManagement(remoteManagementConfig) {
|
|
|
2769
2861
|
logger.info("Remote management stopped.");
|
|
2770
2862
|
return getRemoteManagementState();
|
|
2771
2863
|
}
|
|
2772
|
-
async function handleWebSocketConnection(wsUrl, wsHost, token) {
|
|
2773
|
-
return new Promise((resolve) => {
|
|
2864
|
+
async function handleWebSocketConnection(wsUrl, wsHost, token, onOpenCallback) {
|
|
2865
|
+
return new Promise((resolve, reject) => {
|
|
2774
2866
|
const ws = new import_ws.default(wsUrl, {
|
|
2775
2867
|
headers: { Authorization: `Bearer ${token}` }
|
|
2776
2868
|
});
|
|
2777
2869
|
currentWs = ws;
|
|
2778
2870
|
let heartbeat = null;
|
|
2779
2871
|
let firstMessage = true;
|
|
2780
|
-
|
|
2781
|
-
|
|
2872
|
+
let settled = false;
|
|
2873
|
+
const cleanup = (err) => {
|
|
2874
|
+
if (settled) {
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2877
|
+
settled = true;
|
|
2878
|
+
if (heartbeat) {
|
|
2879
|
+
clearInterval(heartbeat);
|
|
2880
|
+
}
|
|
2782
2881
|
currentWs = null;
|
|
2783
|
-
|
|
2882
|
+
if (err) {
|
|
2883
|
+
reject(err);
|
|
2884
|
+
} else {
|
|
2885
|
+
resolve();
|
|
2886
|
+
}
|
|
2784
2887
|
};
|
|
2785
2888
|
ws.once("open", () => {
|
|
2786
2889
|
printer_default.success(`Connected to ${wsHost}`);
|
|
2787
2890
|
setRemoteManagementState({ status: RemoteManagementStatus.Running, errorMessage: "" });
|
|
2891
|
+
onOpenCallback?.();
|
|
2788
2892
|
heartbeat = setInterval(() => {
|
|
2789
2893
|
if (ws.readyState === import_ws.default.OPEN) ws.ping();
|
|
2790
2894
|
}, PING_INTERVAL_MS);
|
|
@@ -2812,13 +2916,14 @@ async function handleWebSocketConnection(wsUrl, wsHost, token) {
|
|
|
2812
2916
|
ws.on("unexpected-response", (_, res) => {
|
|
2813
2917
|
if (res.statusCode === 401) {
|
|
2814
2918
|
setRemoteManagementState({ status: RemoteManagementStatus.NotRunning, errorMessage: `HTTP ${res.statusCode}` });
|
|
2815
|
-
printer_default.error("Unauthorized. Please enter a valid token.");
|
|
2816
2919
|
logger.error("Unauthorized (401) on remote management connect");
|
|
2920
|
+
cleanup(new RemoteManagementUnauthorizedError());
|
|
2817
2921
|
ws.close();
|
|
2818
2922
|
} else {
|
|
2819
2923
|
logger.warn("Unexpected HTTP response ", { statusCode: res.statusCode });
|
|
2820
2924
|
printer_default.warn(`Unexpected HTTP ${res.statusCode}. Retrying...`);
|
|
2821
2925
|
cleanup();
|
|
2926
|
+
ws.close();
|
|
2822
2927
|
}
|
|
2823
2928
|
});
|
|
2824
2929
|
ws.on("close", (code, reason) => {
|
|
@@ -2830,7 +2935,7 @@ async function handleWebSocketConnection(wsUrl, wsHost, token) {
|
|
|
2830
2935
|
ws.on("error", (err) => {
|
|
2831
2936
|
setRemoteManagementState({ status: RemoteManagementStatus.Error, errorMessage: err.message });
|
|
2832
2937
|
logger.warn("WebSocket error", { error: err.message });
|
|
2833
|
-
printer_default.
|
|
2938
|
+
printer_default.warn(err.message);
|
|
2834
2939
|
cleanup();
|
|
2835
2940
|
});
|
|
2836
2941
|
});
|
|
@@ -2860,6 +2965,58 @@ async function closeRemoteManagement(timeoutMs = 1e4) {
|
|
|
2860
2965
|
return getRemoteManagementState();
|
|
2861
2966
|
}
|
|
2862
2967
|
}
|
|
2968
|
+
function startRemoteManagement(remoteManagementConfig) {
|
|
2969
|
+
if (!remoteManagementConfig.apiKey || remoteManagementConfig.apiKey.trim().length === 0) {
|
|
2970
|
+
return Promise.reject(new Error("Remote management token is required"));
|
|
2971
|
+
}
|
|
2972
|
+
const wsUrl = remoteManagementConfig.serverUrl;
|
|
2973
|
+
const wsHost = extractHostname(wsUrl);
|
|
2974
|
+
logger.info("Remote management mode enabled.");
|
|
2975
|
+
_stopRequested = false;
|
|
2976
|
+
return new Promise((resolve, reject) => {
|
|
2977
|
+
let firstSettled = false;
|
|
2978
|
+
const settleOnce = (err) => {
|
|
2979
|
+
if (firstSettled) {
|
|
2980
|
+
return;
|
|
2981
|
+
}
|
|
2982
|
+
firstSettled = true;
|
|
2983
|
+
if (err) {
|
|
2984
|
+
reject(err);
|
|
2985
|
+
} else {
|
|
2986
|
+
resolve(getRemoteManagementState());
|
|
2987
|
+
}
|
|
2988
|
+
};
|
|
2989
|
+
const runLoop = async () => {
|
|
2990
|
+
const sigintHandler = () => {
|
|
2991
|
+
_stopRequested = true;
|
|
2992
|
+
};
|
|
2993
|
+
process.once("SIGINT", sigintHandler);
|
|
2994
|
+
while (!_stopRequested) {
|
|
2995
|
+
logger.info("Connecting to remote management", { wsUrl });
|
|
2996
|
+
setRemoteManagementState({ status: RemoteManagementStatus.Connecting, errorMessage: "" });
|
|
2997
|
+
try {
|
|
2998
|
+
await handleWebSocketConnection(wsUrl, wsHost, remoteManagementConfig.apiKey, () => settleOnce());
|
|
2999
|
+
} catch (error) {
|
|
3000
|
+
if (error instanceof RemoteManagementUnauthorizedError) {
|
|
3001
|
+
settleOnce(error);
|
|
3002
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
3003
|
+
return;
|
|
3004
|
+
}
|
|
3005
|
+
settleOnce();
|
|
3006
|
+
logger.warn("Remote management connection error", { error: String(error) });
|
|
3007
|
+
}
|
|
3008
|
+
if (_stopRequested) {
|
|
3009
|
+
break;
|
|
3010
|
+
}
|
|
3011
|
+
logger.info("Reconnecting to remote management after disconnect");
|
|
3012
|
+
await sleep(RECONNECT_SLEEP_MS);
|
|
3013
|
+
}
|
|
3014
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
3015
|
+
logger.info("Remote management stopped.");
|
|
3016
|
+
};
|
|
3017
|
+
runLoop().catch((err) => settleOnce(err instanceof Error ? err : new Error(String(err))));
|
|
3018
|
+
});
|
|
3019
|
+
}
|
|
2863
3020
|
function getRemoteManagementState() {
|
|
2864
3021
|
return _remoteManagementState;
|
|
2865
3022
|
}
|
|
@@ -2869,7 +3026,7 @@ function setRemoteManagementState(state, errorMessage) {
|
|
|
2869
3026
|
errorMessage: errorMessage || ""
|
|
2870
3027
|
};
|
|
2871
3028
|
}
|
|
2872
|
-
var import_ws, RECONNECT_SLEEP_MS, PING_INTERVAL_MS, _remoteManagementState, _stopRequested, currentWs;
|
|
3029
|
+
var import_ws, RECONNECT_SLEEP_MS, PING_INTERVAL_MS, RemoteManagementUnauthorizedError, _remoteManagementState, _stopRequested, currentWs;
|
|
2873
3030
|
var init_remoteManagement = __esm({
|
|
2874
3031
|
"src/remote_management/remoteManagement.ts"() {
|
|
2875
3032
|
"use strict";
|
|
@@ -2881,6 +3038,12 @@ var init_remoteManagement = __esm({
|
|
|
2881
3038
|
init_types();
|
|
2882
3039
|
RECONNECT_SLEEP_MS = 5e3;
|
|
2883
3040
|
PING_INTERVAL_MS = 3e4;
|
|
3041
|
+
RemoteManagementUnauthorizedError = class extends Error {
|
|
3042
|
+
constructor() {
|
|
3043
|
+
super("Unauthorized. Please enter a valid token.");
|
|
3044
|
+
this.name = "RemoteManagementUnauthorizedError";
|
|
3045
|
+
}
|
|
3046
|
+
};
|
|
2884
3047
|
_remoteManagementState = {
|
|
2885
3048
|
status: "NOT_RUNNING",
|
|
2886
3049
|
errorMessage: ""
|
|
@@ -3162,7 +3325,9 @@ function removeIPv6Brackets(ip) {
|
|
|
3162
3325
|
}
|
|
3163
3326
|
function isValidServerAddress(host) {
|
|
3164
3327
|
const normalized = removeIPv6Brackets(host.trim());
|
|
3165
|
-
if (!normalized)
|
|
3328
|
+
if (!normalized) {
|
|
3329
|
+
return false;
|
|
3330
|
+
}
|
|
3166
3331
|
return domainRegex.test(normalized) || (0, import_net2.isIP)(normalized) !== 0;
|
|
3167
3332
|
}
|
|
3168
3333
|
function isKeyword(str) {
|
|
@@ -3174,7 +3339,9 @@ function parseUserAndDomain(str) {
|
|
|
3174
3339
|
let server;
|
|
3175
3340
|
let qrCode;
|
|
3176
3341
|
let forceFlag;
|
|
3177
|
-
if (!str)
|
|
3342
|
+
if (!str) {
|
|
3343
|
+
return { token, type, server, qrCode, forceFlag };
|
|
3344
|
+
}
|
|
3178
3345
|
if (str.includes("@")) {
|
|
3179
3346
|
const [user, domain] = str.split("@", 2);
|
|
3180
3347
|
if (isValidServerAddress(domain)) {
|
|
@@ -3227,21 +3394,39 @@ function parseUsers(positionalArgs, explicitToken) {
|
|
|
3227
3394
|
let remaining = [...positionalArgs];
|
|
3228
3395
|
if (typeof explicitToken === "string") {
|
|
3229
3396
|
const parsed = parseUserAndDomain(explicitToken);
|
|
3230
|
-
if (parsed.server)
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
if (parsed.
|
|
3234
|
-
|
|
3397
|
+
if (parsed.server) {
|
|
3398
|
+
server = parsed.server;
|
|
3399
|
+
}
|
|
3400
|
+
if (parsed.type) {
|
|
3401
|
+
type = parsed.type;
|
|
3402
|
+
}
|
|
3403
|
+
if (parsed.token) {
|
|
3404
|
+
token = parsed.token;
|
|
3405
|
+
}
|
|
3406
|
+
if (parsed.forceFlag) {
|
|
3407
|
+
forceFlag = true;
|
|
3408
|
+
}
|
|
3409
|
+
if (parsed.qrCode) {
|
|
3410
|
+
qrCode = true;
|
|
3411
|
+
}
|
|
3235
3412
|
}
|
|
3236
3413
|
if (remaining.length > 0) {
|
|
3237
3414
|
const first = remaining[0];
|
|
3238
3415
|
const parsed = parseUserAndDomain(first);
|
|
3239
3416
|
if (parsed.server) {
|
|
3240
3417
|
server = parsed.server;
|
|
3241
|
-
if (parsed.type)
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
if (parsed.
|
|
3418
|
+
if (parsed.type) {
|
|
3419
|
+
type = parsed.type;
|
|
3420
|
+
}
|
|
3421
|
+
if (parsed.token) {
|
|
3422
|
+
token = parsed.token;
|
|
3423
|
+
}
|
|
3424
|
+
if (parsed.forceFlag) {
|
|
3425
|
+
forceFlag = true;
|
|
3426
|
+
}
|
|
3427
|
+
if (parsed.qrCode) {
|
|
3428
|
+
qrCode = true;
|
|
3429
|
+
}
|
|
3245
3430
|
remaining = remaining.slice(1);
|
|
3246
3431
|
}
|
|
3247
3432
|
}
|
|
@@ -3254,7 +3439,9 @@ function parseType(finalConfig, values, inferredType) {
|
|
|
3254
3439
|
}
|
|
3255
3440
|
}
|
|
3256
3441
|
function parseLocalPort(finalConfig, values) {
|
|
3257
|
-
if (typeof values.localport !== "string")
|
|
3442
|
+
if (typeof values.localport !== "string") {
|
|
3443
|
+
return null;
|
|
3444
|
+
}
|
|
3258
3445
|
let lp = values.localport.trim();
|
|
3259
3446
|
let isHttps = false;
|
|
3260
3447
|
if (lp.startsWith("https://")) {
|
|
@@ -3286,7 +3473,9 @@ function parseLocalPort(finalConfig, values) {
|
|
|
3286
3473
|
}
|
|
3287
3474
|
function isValidHostAddress(host) {
|
|
3288
3475
|
const normalized = removeIPv6Brackets(host.trim());
|
|
3289
|
-
if (normalized.length === 0)
|
|
3476
|
+
if (normalized.length === 0) {
|
|
3477
|
+
return false;
|
|
3478
|
+
}
|
|
3290
3479
|
return normalized === "localhost" || (0, import_net2.isIP)(normalized) !== 0;
|
|
3291
3480
|
}
|
|
3292
3481
|
function ipv6SafeSplitColon(s) {
|
|
@@ -3329,7 +3518,9 @@ function parseDefaultForwarding(forwarding) {
|
|
|
3329
3518
|
}
|
|
3330
3519
|
function parseAdditionalForwarding(forwarding) {
|
|
3331
3520
|
const toPort = (v) => {
|
|
3332
|
-
if (!v)
|
|
3521
|
+
if (!v) {
|
|
3522
|
+
return null;
|
|
3523
|
+
}
|
|
3333
3524
|
const n = parseInt(v, 10);
|
|
3334
3525
|
return Number.isNaN(n) ? null : n;
|
|
3335
3526
|
};
|
|
@@ -3408,7 +3599,9 @@ function parseReverseTunnelAddr(finalConfig, values, primaryType) {
|
|
|
3408
3599
|
});
|
|
3409
3600
|
} else if (slicedForwarding.length === 4) {
|
|
3410
3601
|
const parsed = parseAdditionalForwarding(forwarding);
|
|
3411
|
-
if (parsed instanceof Error)
|
|
3602
|
+
if (parsed instanceof Error) {
|
|
3603
|
+
return parsed;
|
|
3604
|
+
}
|
|
3412
3605
|
forwardingData.push(parsed);
|
|
3413
3606
|
} else {
|
|
3414
3607
|
return new Error(
|
|
@@ -3420,7 +3613,9 @@ function parseReverseTunnelAddr(finalConfig, values, primaryType) {
|
|
|
3420
3613
|
return null;
|
|
3421
3614
|
}
|
|
3422
3615
|
function parseLocalTunnelAddr(finalConfig, values) {
|
|
3423
|
-
if (!Array.isArray(values.L) || values.L.length === 0)
|
|
3616
|
+
if (!Array.isArray(values.L) || values.L.length === 0) {
|
|
3617
|
+
return null;
|
|
3618
|
+
}
|
|
3424
3619
|
const firstL = values.L[0];
|
|
3425
3620
|
const parts = ipv6SafeSplitColon(firstL);
|
|
3426
3621
|
let debuggerHost = "localhost";
|
|
@@ -3444,7 +3639,9 @@ function parseLocalTunnelAddr(finalConfig, values) {
|
|
|
3444
3639
|
}
|
|
3445
3640
|
function parseDebugger(finalConfig, values) {
|
|
3446
3641
|
let dbg = values.debugger;
|
|
3447
|
-
if (typeof dbg !== "string")
|
|
3642
|
+
if (typeof dbg !== "string") {
|
|
3643
|
+
return;
|
|
3644
|
+
}
|
|
3448
3645
|
dbg = dbg.startsWith(":") ? dbg.slice(1) : dbg;
|
|
3449
3646
|
const d = parseInt(dbg, 10);
|
|
3450
3647
|
if (!Number.isNaN(d) && isValidPort(d)) {
|
|
@@ -3503,7 +3700,9 @@ function isSaveConfOption(values) {
|
|
|
3503
3700
|
}
|
|
3504
3701
|
function parseServe(finalConfig, values) {
|
|
3505
3702
|
const sv = values.serve;
|
|
3506
|
-
if (typeof sv !== "string" || sv.trim().length === 0)
|
|
3703
|
+
if (typeof sv !== "string" || sv.trim().length === 0) {
|
|
3704
|
+
return null;
|
|
3705
|
+
}
|
|
3507
3706
|
finalConfig.optional.serve = sv;
|
|
3508
3707
|
return null;
|
|
3509
3708
|
}
|
|
@@ -3555,18 +3754,32 @@ async function buildFinalConfig(values, positionals) {
|
|
|
3555
3754
|
type = parseType(finalConfig, values, type);
|
|
3556
3755
|
parseToken(finalConfig, token || values.token);
|
|
3557
3756
|
const dbgErr = parseDebugger(finalConfig, values);
|
|
3558
|
-
if (dbgErr instanceof Error)
|
|
3757
|
+
if (dbgErr instanceof Error) {
|
|
3758
|
+
throw dbgErr;
|
|
3759
|
+
}
|
|
3559
3760
|
const lpErr = parseLocalPort(finalConfig, values);
|
|
3560
|
-
if (lpErr instanceof Error)
|
|
3761
|
+
if (lpErr instanceof Error) {
|
|
3762
|
+
throw lpErr;
|
|
3763
|
+
}
|
|
3561
3764
|
const rErr = parseReverseTunnelAddr(finalConfig, values, type);
|
|
3562
|
-
if (rErr instanceof Error)
|
|
3765
|
+
if (rErr instanceof Error) {
|
|
3766
|
+
throw rErr;
|
|
3767
|
+
}
|
|
3563
3768
|
const lErr = parseLocalTunnelAddr(finalConfig, values);
|
|
3564
|
-
if (lErr instanceof Error)
|
|
3769
|
+
if (lErr instanceof Error) {
|
|
3770
|
+
throw lErr;
|
|
3771
|
+
}
|
|
3565
3772
|
const serveErr = parseServe(finalConfig, values);
|
|
3566
|
-
if (serveErr instanceof Error)
|
|
3773
|
+
if (serveErr instanceof Error) {
|
|
3774
|
+
throw serveErr;
|
|
3775
|
+
}
|
|
3567
3776
|
const autoReconnectErr = parseAutoReconnect(finalConfig, values);
|
|
3568
|
-
if (autoReconnectErr instanceof Error)
|
|
3569
|
-
|
|
3777
|
+
if (autoReconnectErr instanceof Error) {
|
|
3778
|
+
throw autoReconnectErr;
|
|
3779
|
+
}
|
|
3780
|
+
if (forceFlag || values.force) {
|
|
3781
|
+
finalConfig.force = true;
|
|
3782
|
+
}
|
|
3570
3783
|
parseArgs(finalConfig, remainingPositionals);
|
|
3571
3784
|
storeJson(finalConfig, saveconf);
|
|
3572
3785
|
return finalConfig;
|
|
@@ -3603,15 +3816,26 @@ function isAttachedReverseOrLocalFlag(arg) {
|
|
|
3603
3816
|
return /^-[RL].+/.test(arg);
|
|
3604
3817
|
}
|
|
3605
3818
|
function shouldMergeReverseOrLocalFragment(current, next) {
|
|
3606
|
-
if (next.startsWith("-"))
|
|
3607
|
-
|
|
3819
|
+
if (next.startsWith("-")) {
|
|
3820
|
+
return false;
|
|
3821
|
+
}
|
|
3822
|
+
if (next.startsWith(".")) {
|
|
3823
|
+
return true;
|
|
3824
|
+
}
|
|
3608
3825
|
const body = current.slice(2);
|
|
3609
|
-
if (body.endsWith(":"))
|
|
3610
|
-
|
|
3826
|
+
if (body.endsWith(":")) {
|
|
3827
|
+
return true;
|
|
3828
|
+
}
|
|
3829
|
+
if (body.includes("//") && !body.includes(":")) {
|
|
3830
|
+
return true;
|
|
3831
|
+
}
|
|
3611
3832
|
return false;
|
|
3612
3833
|
}
|
|
3613
3834
|
function preprocessWindowsArgs(args) {
|
|
3614
|
-
if (os2.platform() !== "win32")
|
|
3835
|
+
if (os2.platform() !== "win32") {
|
|
3836
|
+
return args;
|
|
3837
|
+
}
|
|
3838
|
+
;
|
|
3615
3839
|
const out = [];
|
|
3616
3840
|
let i = 0;
|
|
3617
3841
|
while (i < args.length) {
|
|
@@ -3698,13 +3922,12 @@ var init_getFreePort = __esm({
|
|
|
3698
3922
|
async function createQrCodes(urls) {
|
|
3699
3923
|
const codes = [];
|
|
3700
3924
|
for (const url of urls) {
|
|
3701
|
-
const
|
|
3702
|
-
type: "
|
|
3703
|
-
|
|
3704
|
-
margin: 0,
|
|
3925
|
+
const raw = await import_qrcode.default.toString(url, {
|
|
3926
|
+
type: "utf8",
|
|
3927
|
+
margin: 2,
|
|
3705
3928
|
errorCorrectionLevel: "L"
|
|
3706
3929
|
});
|
|
3707
|
-
codes.push(
|
|
3930
|
+
codes.push(raw);
|
|
3708
3931
|
}
|
|
3709
3932
|
return codes;
|
|
3710
3933
|
}
|
|
@@ -3722,6 +3945,7 @@ function getTuiConfig() {
|
|
|
3722
3945
|
return {
|
|
3723
3946
|
maxRequestPairs: defaultTuiConfig.maxRequestPairs,
|
|
3724
3947
|
visibleRequestCount: defaultTuiConfig.visibleRequestCount,
|
|
3948
|
+
visibleUrlCount: defaultTuiConfig.visibleUrlCount,
|
|
3725
3949
|
viewportScrollMargin: defaultTuiConfig.viewportScrollMargin,
|
|
3726
3950
|
inactivityHttpSelectorTimeoutMs: defaultTuiConfig.inactivityHttpSelectorTimeoutMs
|
|
3727
3951
|
};
|
|
@@ -3734,6 +3958,7 @@ var init_config = __esm({
|
|
|
3734
3958
|
defaultTuiConfig = {
|
|
3735
3959
|
maxRequestPairs: 100,
|
|
3736
3960
|
visibleRequestCount: 10,
|
|
3961
|
+
visibleUrlCount: 7,
|
|
3737
3962
|
viewportScrollMargin: 2,
|
|
3738
3963
|
inactivityHttpSelectorTimeoutMs: 1e4
|
|
3739
3964
|
};
|
|
@@ -3974,7 +4199,7 @@ function createFullUI(screen, urls, greet, tunnelConfig) {
|
|
|
3974
4199
|
width: "100%-2",
|
|
3975
4200
|
height: `100%-${lowerSectionTop + 6}`
|
|
3976
4201
|
});
|
|
3977
|
-
const isQrCodeRequested = tunnelConfig?.
|
|
4202
|
+
const isQrCodeRequested = tunnelConfig?.isQRCode || false;
|
|
3978
4203
|
const requestsBox = import_blessed.default.box({
|
|
3979
4204
|
parent: lowerSection,
|
|
3980
4205
|
top: 0,
|
|
@@ -4134,8 +4359,24 @@ var init_utils = __esm({
|
|
|
4134
4359
|
// src/tui/blessed/components/DisplayUpdaters.ts
|
|
4135
4360
|
function updateUrlsDisplay(urlsBox, screen, urls, currentQrIndex) {
|
|
4136
4361
|
if (!urlsBox) return;
|
|
4137
|
-
|
|
4138
|
-
|
|
4362
|
+
const config = getTuiConfig();
|
|
4363
|
+
const { visibleUrlCount } = config;
|
|
4364
|
+
let viewportStart = 0;
|
|
4365
|
+
if (urls.length > visibleUrlCount) {
|
|
4366
|
+
viewportStart = Math.max(0, Math.min(
|
|
4367
|
+
currentQrIndex - Math.floor(visibleUrlCount / 2),
|
|
4368
|
+
urls.length - visibleUrlCount
|
|
4369
|
+
));
|
|
4370
|
+
}
|
|
4371
|
+
const viewportEnd = Math.min(viewportStart + visibleUrlCount, urls.length);
|
|
4372
|
+
const visibleUrls = urls.slice(viewportStart, viewportEnd);
|
|
4373
|
+
let content = "{green-fg}{bold}Public URLs{/bold}{/green-fg}";
|
|
4374
|
+
if (viewportStart > 0) {
|
|
4375
|
+
content += ` {gray-fg}\u2191 ${viewportStart} more{/gray-fg}`;
|
|
4376
|
+
}
|
|
4377
|
+
content += "\n";
|
|
4378
|
+
visibleUrls.forEach((url, i) => {
|
|
4379
|
+
const index = viewportStart + i;
|
|
4139
4380
|
const isSelected = index === currentQrIndex;
|
|
4140
4381
|
const prefix = isSelected ? "\u2192 " : "\u2022 ";
|
|
4141
4382
|
const color = isSelected ? "yellow" : "magenta";
|
|
@@ -4147,6 +4388,11 @@ function updateUrlsDisplay(urlsBox, screen, urls, currentQrIndex) {
|
|
|
4147
4388
|
`;
|
|
4148
4389
|
}
|
|
4149
4390
|
});
|
|
4391
|
+
const itemsBelow = urls.length - viewportEnd;
|
|
4392
|
+
if (itemsBelow > 0) {
|
|
4393
|
+
content += `{gray-fg}\u2193 ${itemsBelow} more{/gray-fg}
|
|
4394
|
+
`;
|
|
4395
|
+
}
|
|
4150
4396
|
urlsBox.setContent(content);
|
|
4151
4397
|
screen.render();
|
|
4152
4398
|
}
|
|
@@ -4859,7 +5105,7 @@ var init_TunnelTui = __esm({
|
|
|
4859
5105
|
}
|
|
4860
5106
|
}
|
|
4861
5107
|
async generateQrCodes() {
|
|
4862
|
-
if (this.tunnelConfig?.
|
|
5108
|
+
if (this.tunnelConfig?.isQRCode && this.urls.length > 0) {
|
|
4863
5109
|
this.qrCodes = await createQrCodes(this.urls);
|
|
4864
5110
|
this.updateQrCodeDisplay();
|
|
4865
5111
|
}
|
|
@@ -5096,7 +5342,7 @@ async function startCli(finalConfig, manager) {
|
|
|
5096
5342
|
});
|
|
5097
5343
|
}
|
|
5098
5344
|
manager2.registerWorkerErrorListner(tunnel.tunnelid, (_tunnelid, error) => {
|
|
5099
|
-
printer_default.
|
|
5345
|
+
printer_default.fatal(`${error.message}`);
|
|
5100
5346
|
});
|
|
5101
5347
|
await manager2.startTunnel(tunnel.tunnelid);
|
|
5102
5348
|
printer_default.stopSpinnerSuccess(" Connected to Pinggy");
|
|
@@ -5221,7 +5467,7 @@ async function startCli(finalConfig, manager) {
|
|
|
5221
5467
|
}
|
|
5222
5468
|
} catch (err) {
|
|
5223
5469
|
printer_default.stopSpinnerFail("Failed to connect");
|
|
5224
|
-
printer_default.
|
|
5470
|
+
printer_default.fatal(err.message || "Unknown error");
|
|
5225
5471
|
throw err;
|
|
5226
5472
|
}
|
|
5227
5473
|
}
|
|
@@ -5249,6 +5495,7 @@ var init_starCli = __esm({
|
|
|
5249
5495
|
// src/main.ts
|
|
5250
5496
|
var main_exports = {};
|
|
5251
5497
|
__export(main_exports, {
|
|
5498
|
+
RemoteManagementUnauthorizedError: () => RemoteManagementUnauthorizedError,
|
|
5252
5499
|
TunnelManager: () => TunnelManager,
|
|
5253
5500
|
TunnelOperations: () => TunnelOperations,
|
|
5254
5501
|
closeRemoteManagement: () => closeRemoteManagement,
|
|
@@ -5278,9 +5525,8 @@ async function main() {
|
|
|
5278
5525
|
}
|
|
5279
5526
|
const parseResult = await parseRemoteManagement(values);
|
|
5280
5527
|
if (parseResult?.ok === false) {
|
|
5281
|
-
printer_default.error(parseResult.error);
|
|
5282
5528
|
logger.error("Failed to initiate remote management:", parseResult.error);
|
|
5283
|
-
|
|
5529
|
+
printer_default.fatal(parseResult.error);
|
|
5284
5530
|
}
|
|
5285
5531
|
logger.debug("Building final config from CLI values and positionals", { values, positionals });
|
|
5286
5532
|
const finalConfig = await buildFinalConfig(values, positionals);
|
|
@@ -5288,7 +5534,7 @@ async function main() {
|
|
|
5288
5534
|
await startCli(finalConfig, manager);
|
|
5289
5535
|
} catch (error) {
|
|
5290
5536
|
logger.error("Unhandled error in CLI:", error);
|
|
5291
|
-
printer_default.
|
|
5537
|
+
printer_default.fatal(error);
|
|
5292
5538
|
}
|
|
5293
5539
|
}
|
|
5294
5540
|
var import_url2, import_process, import_fs5, currentFile, entryFile;
|
|
@@ -5328,6 +5574,7 @@ var init_main = __esm({
|
|
|
5328
5574
|
// src/index.ts
|
|
5329
5575
|
var index_exports = {};
|
|
5330
5576
|
__export(index_exports, {
|
|
5577
|
+
RemoteManagementUnauthorizedError: () => RemoteManagementUnauthorizedError,
|
|
5331
5578
|
TunnelErrorCodeType: () => TunnelErrorCodeType,
|
|
5332
5579
|
TunnelManager: () => TunnelManager,
|
|
5333
5580
|
TunnelOperations: () => TunnelOperations,
|
|
@@ -5336,7 +5583,8 @@ __export(index_exports, {
|
|
|
5336
5583
|
closeRemoteManagement: () => closeRemoteManagement,
|
|
5337
5584
|
enablePackageLogging: () => enablePackageLogging,
|
|
5338
5585
|
getRemoteManagementState: () => getRemoteManagementState,
|
|
5339
|
-
initiateRemoteManagement: () => initiateRemoteManagement
|
|
5586
|
+
initiateRemoteManagement: () => initiateRemoteManagement,
|
|
5587
|
+
startRemoteManagement: () => startRemoteManagement
|
|
5340
5588
|
});
|
|
5341
5589
|
module.exports = __toCommonJS(index_exports);
|
|
5342
5590
|
init_cjs_shims();
|
|
@@ -5442,11 +5690,11 @@ async function verifyAndLoad() {
|
|
|
5442
5690
|
await Promise.resolve().then(() => (init_main(), main_exports));
|
|
5443
5691
|
}
|
|
5444
5692
|
verifyAndLoad().catch((err) => {
|
|
5445
|
-
printer_default.
|
|
5446
|
-
process.exit(1);
|
|
5693
|
+
printer_default.fatal(`Failed to start CLI:, ${err}`);
|
|
5447
5694
|
});
|
|
5448
5695
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5449
5696
|
0 && (module.exports = {
|
|
5697
|
+
RemoteManagementUnauthorizedError,
|
|
5450
5698
|
TunnelErrorCodeType,
|
|
5451
5699
|
TunnelManager,
|
|
5452
5700
|
TunnelOperations,
|
|
@@ -5455,5 +5703,6 @@ verifyAndLoad().catch((err) => {
|
|
|
5455
5703
|
closeRemoteManagement,
|
|
5456
5704
|
enablePackageLogging,
|
|
5457
5705
|
getRemoteManagementState,
|
|
5458
|
-
initiateRemoteManagement
|
|
5706
|
+
initiateRemoteManagement,
|
|
5707
|
+
startRemoteManagement
|
|
5459
5708
|
});
|