pinggy 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/{chunk-65R2GMKQ.js → chunk-JD3U36U5.js} +726 -177
- package/dist/index.cjs +830 -247
- package/dist/index.d.cts +105 -75
- package/dist/index.d.ts +105 -75
- package/dist/index.js +2 -2
- package/dist/{main-2QDG7PWL.js → main-VIBOPJ64.js} +51 -32
- package/dist/workers/file_serve_worker.cjs +1181 -2
- package/dist/workers/file_serve_worker.js +1181 -2
- package/jest.config.cjs +13 -0
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -118,6 +118,9 @@ var init_printer = __esm({
|
|
|
118
118
|
console.error(import_picocolors2.default.red(import_picocolors2.default.bold("\u2716 Error:")), import_picocolors2.default.red(msg));
|
|
119
119
|
process.exit(1);
|
|
120
120
|
}
|
|
121
|
+
static red(message) {
|
|
122
|
+
return import_picocolors2.default.red(message);
|
|
123
|
+
}
|
|
121
124
|
static warn(message) {
|
|
122
125
|
console.warn(import_picocolors2.default.yellow(import_picocolors2.default.bold("\u26A0 Warning:")), import_picocolors2.default.yellow(message));
|
|
123
126
|
}
|
|
@@ -283,22 +286,32 @@ function isValidPort(p) {
|
|
|
283
286
|
return Number.isInteger(p) && p > 0 && p < 65536;
|
|
284
287
|
}
|
|
285
288
|
function getVersion() {
|
|
286
|
-
|
|
289
|
+
try {
|
|
290
|
+
const packageJsonPath = (0, import_path3.join)(__dirname, "../package.json");
|
|
291
|
+
const pkg = JSON.parse((0, import_fs3.readFileSync)(packageJsonPath, "utf-8"));
|
|
292
|
+
return pkg.version ?? "";
|
|
293
|
+
} catch (error) {
|
|
294
|
+
printer_default.error("Error reading version info");
|
|
295
|
+
return "";
|
|
296
|
+
}
|
|
287
297
|
}
|
|
288
|
-
var
|
|
298
|
+
var import_fs3, import_crypto, import_url, import_path3, __filename2, __dirname;
|
|
289
299
|
var init_util = __esm({
|
|
290
300
|
"src/utils/util.ts"() {
|
|
291
301
|
"use strict";
|
|
292
302
|
init_cjs_shims();
|
|
293
|
-
|
|
303
|
+
import_fs3 = require("fs");
|
|
294
304
|
import_crypto = require("crypto");
|
|
295
|
-
|
|
296
|
-
|
|
305
|
+
import_url = require("url");
|
|
306
|
+
import_path3 = require("path");
|
|
307
|
+
init_printer();
|
|
308
|
+
__filename2 = (0, import_url.fileURLToPath)(importMetaUrl);
|
|
309
|
+
__dirname = (0, import_path3.dirname)(__filename2);
|
|
297
310
|
}
|
|
298
311
|
});
|
|
299
312
|
|
|
300
313
|
// src/tunnel_manager/TunnelManager.ts
|
|
301
|
-
var import_pinggy2, import_node_path, import_node_worker_threads, import_node_url,
|
|
314
|
+
var import_pinggy2, import_node_path, import_node_worker_threads, import_node_url, __filename3, __dirname2, TunnelManager;
|
|
302
315
|
var init_TunnelManager = __esm({
|
|
303
316
|
"src/tunnel_manager/TunnelManager.ts"() {
|
|
304
317
|
"use strict";
|
|
@@ -310,8 +323,8 @@ var init_TunnelManager = __esm({
|
|
|
310
323
|
import_node_url = require("url");
|
|
311
324
|
init_printer();
|
|
312
325
|
init_util();
|
|
313
|
-
|
|
314
|
-
|
|
326
|
+
__filename3 = (0, import_node_url.fileURLToPath)(importMetaUrl);
|
|
327
|
+
__dirname2 = import_node_path.default.dirname(__filename3);
|
|
315
328
|
TunnelManager = class _TunnelManager {
|
|
316
329
|
constructor() {
|
|
317
330
|
this.tunnelsByTunnelId = /* @__PURE__ */ new Map();
|
|
@@ -319,6 +332,7 @@ var init_TunnelManager = __esm({
|
|
|
319
332
|
this.tunnelStats = /* @__PURE__ */ new Map();
|
|
320
333
|
this.tunnelStatsListeners = /* @__PURE__ */ new Map();
|
|
321
334
|
this.tunnelErrorListeners = /* @__PURE__ */ new Map();
|
|
335
|
+
this.tunnelPollingErrorListeners = /* @__PURE__ */ new Map();
|
|
322
336
|
this.tunnelDisconnectListeners = /* @__PURE__ */ new Map();
|
|
323
337
|
this.tunnelWorkerErrorListeners = /* @__PURE__ */ new Map();
|
|
324
338
|
this.tunnelStartListeners = /* @__PURE__ */ new Map();
|
|
@@ -335,12 +349,9 @@ var init_TunnelManager = __esm({
|
|
|
335
349
|
}
|
|
336
350
|
/**
|
|
337
351
|
* Creates a new managed tunnel instance with the given configuration.
|
|
338
|
-
*
|
|
352
|
+
* Optionally builds the config with forwarding rules based on buildConfig flag.
|
|
339
353
|
*
|
|
340
354
|
* @param config - The tunnel configuration options
|
|
341
|
-
* @param config.configid - Unique identifier for the tunnel configuration
|
|
342
|
-
* @param config.tunnelid - Optional custom tunnel identifier. If not provided, a random UUID will be generated
|
|
343
|
-
* @param config.additionalForwarding - Optional array of additional forwarding configurations
|
|
344
355
|
*
|
|
345
356
|
* @throws {Error} When configId is invalid or empty
|
|
346
357
|
* @throws {Error} When a tunnel with the given configId already exists
|
|
@@ -349,24 +360,19 @@ var init_TunnelManager = __esm({
|
|
|
349
360
|
* status information, and statistics
|
|
350
361
|
*/
|
|
351
362
|
async createTunnel(config) {
|
|
352
|
-
const {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
throw new Error(`Tunnel with configId "${configid}" already exists`);
|
|
363
|
+
const { configId, tunnelid: requestedTunnelId, tunnelName, name, serve } = config;
|
|
364
|
+
const tunnelid = requestedTunnelId || getRandomId();
|
|
365
|
+
const autoReconnect = config.autoReconnect || false;
|
|
366
|
+
if (!configId || typeof configId !== "string" || configId.trim() === "") {
|
|
367
|
+
throw new Error("configId is required and must be a non-empty string");
|
|
358
368
|
}
|
|
359
|
-
const tunnelid = config.tunnelid || getRandomId();
|
|
360
|
-
const configWithForwarding = this.buildPinggyConfig(config, additionalForwarding);
|
|
361
369
|
return this._createTunnelWithProcessedConfig({
|
|
362
|
-
|
|
370
|
+
configId,
|
|
363
371
|
tunnelid,
|
|
364
|
-
tunnelName,
|
|
372
|
+
tunnelName: tunnelName || name,
|
|
365
373
|
originalConfig: config,
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
serve: config.serve,
|
|
369
|
-
autoReconnect: config.autoReconnect !== void 0 ? config.autoReconnect : false
|
|
374
|
+
serve,
|
|
375
|
+
autoReconnect
|
|
370
376
|
});
|
|
371
377
|
}
|
|
372
378
|
/**
|
|
@@ -380,7 +386,8 @@ var init_TunnelManager = __esm({
|
|
|
380
386
|
async _createTunnelWithProcessedConfig(params) {
|
|
381
387
|
let instance;
|
|
382
388
|
try {
|
|
383
|
-
instance
|
|
389
|
+
logger.debug("Creating tunnel instance with processed config", params.originalConfig);
|
|
390
|
+
instance = await import_pinggy2.pinggy.createTunnel(params.originalConfig);
|
|
384
391
|
} catch (e) {
|
|
385
392
|
logger.error("Error creating tunnel instance:", e);
|
|
386
393
|
throw e;
|
|
@@ -388,12 +395,10 @@ var init_TunnelManager = __esm({
|
|
|
388
395
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
389
396
|
const managed = {
|
|
390
397
|
tunnelid: params.tunnelid,
|
|
391
|
-
|
|
398
|
+
configId: params.configId,
|
|
392
399
|
tunnelName: params.tunnelName,
|
|
393
400
|
instance,
|
|
394
401
|
tunnelConfig: params.originalConfig,
|
|
395
|
-
configWithForwarding: params.configWithForwarding,
|
|
396
|
-
additionalForwarding: params.additionalForwarding,
|
|
397
402
|
serve: params.serve,
|
|
398
403
|
warnings: [],
|
|
399
404
|
isStopped: false,
|
|
@@ -407,6 +412,7 @@ var init_TunnelManager = __esm({
|
|
|
407
412
|
});
|
|
408
413
|
this.setupStatsCallback(params.tunnelid, managed);
|
|
409
414
|
this.setupErrorCallback(params.tunnelid, managed);
|
|
415
|
+
this.setupTunnelPollingErrorCallback(params.tunnelid, managed);
|
|
410
416
|
this.setupDisconnectCallback(params.tunnelid, managed);
|
|
411
417
|
this.setupWillReconnectCallback(params.tunnelid, managed);
|
|
412
418
|
this.setupReconnectingCallback(params.tunnelid, managed);
|
|
@@ -414,44 +420,10 @@ var init_TunnelManager = __esm({
|
|
|
414
420
|
this.setupReconnectionFailedCallback(params.tunnelid, managed);
|
|
415
421
|
this.setUpTunnelWorkerErrorCallback(params.tunnelid, managed);
|
|
416
422
|
this.tunnelsByTunnelId.set(params.tunnelid, managed);
|
|
417
|
-
this.tunnelsByConfigId.set(params.
|
|
418
|
-
logger.info("Tunnel created", {
|
|
423
|
+
this.tunnelsByConfigId.set(params.configId, managed);
|
|
424
|
+
logger.info("Tunnel created", { configId: params.configId, tunnelId: params.tunnelid });
|
|
419
425
|
return managed;
|
|
420
426
|
}
|
|
421
|
-
/**
|
|
422
|
-
* Builds the Pinggy configuration by merging the default forwarding rule
|
|
423
|
-
* with additional forwarding rules from additionalForwarding array.
|
|
424
|
-
*
|
|
425
|
-
* @param config - The base Pinggy configuration
|
|
426
|
-
* @param additionalForwarding - Optional array of additional forwarding rules
|
|
427
|
-
* @returns Modified PinggyOptions
|
|
428
|
-
*/
|
|
429
|
-
buildPinggyConfig(config, additionalForwarding) {
|
|
430
|
-
const forwardingRules = [];
|
|
431
|
-
if (config.forwarding) {
|
|
432
|
-
forwardingRules.push({
|
|
433
|
-
type: config.tunnelType && config.tunnelType[0] || "http",
|
|
434
|
-
address: config.forwarding
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
if (Array.isArray(additionalForwarding) && additionalForwarding.length > 0) {
|
|
438
|
-
for (const rule of additionalForwarding) {
|
|
439
|
-
if (rule && rule.localDomain && rule.localPort && rule.remoteDomain && isValidPort(rule.localPort)) {
|
|
440
|
-
const forwardingRule = {
|
|
441
|
-
type: rule.protocol,
|
|
442
|
-
// In Future we can make this dynamic based on user input
|
|
443
|
-
address: `${rule.localDomain}:${rule.localPort}`,
|
|
444
|
-
listenAddress: rule.remotePort && isValidPort(rule.remotePort) ? `${rule.remoteDomain}:${rule.remotePort}` : rule.remoteDomain
|
|
445
|
-
};
|
|
446
|
-
forwardingRules.push(forwardingRule);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
return {
|
|
451
|
-
...config,
|
|
452
|
-
forwarding: forwardingRules.length > 0 ? forwardingRules : config.forwarding
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
427
|
/**
|
|
456
428
|
* Start a tunnel that was created but not yet started
|
|
457
429
|
*/
|
|
@@ -463,7 +435,7 @@ var init_TunnelManager = __esm({
|
|
|
463
435
|
try {
|
|
464
436
|
urls = await managed.instance.start();
|
|
465
437
|
} catch (error) {
|
|
466
|
-
logger.
|
|
438
|
+
logger.warn("Failed to start tunnel", { tunnelId, error });
|
|
467
439
|
throw error;
|
|
468
440
|
}
|
|
469
441
|
logger.info("Tunnel started", { tunnelId, urls });
|
|
@@ -499,7 +471,7 @@ var init_TunnelManager = __esm({
|
|
|
499
471
|
stopTunnel(tunnelId) {
|
|
500
472
|
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
501
473
|
if (!managed) throw new Error(`Tunnel "${tunnelId}" not found`);
|
|
502
|
-
logger.info("Stopping tunnel", { tunnelId, configId: managed.
|
|
474
|
+
logger.info("Stopping tunnel", { tunnelId, configId: managed.configId });
|
|
503
475
|
try {
|
|
504
476
|
managed.instance.stop();
|
|
505
477
|
if (managed.serveWorker) {
|
|
@@ -511,6 +483,7 @@ var init_TunnelManager = __esm({
|
|
|
511
483
|
this.tunnelStats.delete(tunnelId);
|
|
512
484
|
this.tunnelStatsListeners.delete(tunnelId);
|
|
513
485
|
this.tunnelErrorListeners.delete(tunnelId);
|
|
486
|
+
this.tunnelPollingErrorListeners.delete(tunnelId);
|
|
514
487
|
this.tunnelDisconnectListeners.delete(tunnelId);
|
|
515
488
|
this.tunnelWorkerErrorListeners.delete(tunnelId);
|
|
516
489
|
this.tunnelStartListeners.delete(tunnelId);
|
|
@@ -522,8 +495,8 @@ var init_TunnelManager = __esm({
|
|
|
522
495
|
managed.warnings = managed.warnings ?? [];
|
|
523
496
|
managed.isStopped = true;
|
|
524
497
|
managed.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
525
|
-
logger.info("Tunnel stopped", { tunnelId, configId: managed.
|
|
526
|
-
return {
|
|
498
|
+
logger.info("Tunnel stopped", { tunnelId, configId: managed.configId });
|
|
499
|
+
return { configId: managed.configId, tunnelid: managed.tunnelid };
|
|
527
500
|
} catch (error) {
|
|
528
501
|
logger.error("Failed to stop tunnel", { tunnelId, error });
|
|
529
502
|
throw error;
|
|
@@ -556,11 +529,10 @@ var init_TunnelManager = __esm({
|
|
|
556
529
|
const tunnelList = await Promise.all(Array.from(this.tunnelsByTunnelId.values()).map(async (tunnel) => {
|
|
557
530
|
return {
|
|
558
531
|
tunnelid: tunnel.tunnelid,
|
|
559
|
-
|
|
532
|
+
configId: tunnel.configId,
|
|
560
533
|
tunnelName: tunnel.tunnelName,
|
|
561
534
|
tunnelConfig: tunnel.tunnelConfig,
|
|
562
535
|
remoteurls: !tunnel.isStopped ? await this.getTunnelUrls(tunnel.tunnelid) : [],
|
|
563
|
-
additionalForwarding: tunnel.additionalForwarding,
|
|
564
536
|
serve: tunnel.serve
|
|
565
537
|
};
|
|
566
538
|
}));
|
|
@@ -601,6 +573,15 @@ var init_TunnelManager = __esm({
|
|
|
601
573
|
this.tunnelsByConfigId.clear();
|
|
602
574
|
this.tunnelStats.clear();
|
|
603
575
|
this.tunnelStatsListeners.clear();
|
|
576
|
+
this.tunnelErrorListeners.clear();
|
|
577
|
+
this.tunnelPollingErrorListeners.clear();
|
|
578
|
+
this.tunnelDisconnectListeners.clear();
|
|
579
|
+
this.tunnelWorkerErrorListeners.clear();
|
|
580
|
+
this.tunnelStartListeners.clear();
|
|
581
|
+
this.tunnelWillReconnectListeners.clear();
|
|
582
|
+
this.tunnelReconnectingListeners.clear();
|
|
583
|
+
this.tunnelReconnectionCompletedListeners.clear();
|
|
584
|
+
this.tunnelReconnectionFailedListeners.clear();
|
|
604
585
|
logger.info("All tunnels stopped and cleared");
|
|
605
586
|
}
|
|
606
587
|
/**
|
|
@@ -621,7 +602,7 @@ var init_TunnelManager = __esm({
|
|
|
621
602
|
return false;
|
|
622
603
|
}
|
|
623
604
|
this._cleanupTunnelRecords(managed);
|
|
624
|
-
logger.info("Removed stopped tunnel records", { tunnelId, configId: managed.
|
|
605
|
+
logger.info("Removed stopped tunnel records", { tunnelId, configId: managed.configId });
|
|
625
606
|
return true;
|
|
626
607
|
}
|
|
627
608
|
/**
|
|
@@ -648,6 +629,7 @@ var init_TunnelManager = __esm({
|
|
|
648
629
|
this.tunnelStats.delete(managed.tunnelid);
|
|
649
630
|
this.tunnelStatsListeners.delete(managed.tunnelid);
|
|
650
631
|
this.tunnelErrorListeners.delete(managed.tunnelid);
|
|
632
|
+
this.tunnelPollingErrorListeners.delete(managed.tunnelid);
|
|
651
633
|
this.tunnelDisconnectListeners.delete(managed.tunnelid);
|
|
652
634
|
this.tunnelWorkerErrorListeners.delete(managed.tunnelid);
|
|
653
635
|
this.tunnelStartListeners.delete(managed.tunnelid);
|
|
@@ -656,7 +638,7 @@ var init_TunnelManager = __esm({
|
|
|
656
638
|
this.tunnelReconnectionCompletedListeners.delete(managed.tunnelid);
|
|
657
639
|
this.tunnelReconnectionFailedListeners.delete(managed.tunnelid);
|
|
658
640
|
this.tunnelsByTunnelId.delete(managed.tunnelid);
|
|
659
|
-
this.tunnelsByConfigId.delete(managed.
|
|
641
|
+
this.tunnelsByConfigId.delete(managed.configId);
|
|
660
642
|
} catch (e) {
|
|
661
643
|
logger.warn("Failed cleaning up tunnel records", { tunnelId: managed.tunnelid, error: e });
|
|
662
644
|
}
|
|
@@ -717,21 +699,20 @@ var init_TunnelManager = __esm({
|
|
|
717
699
|
}
|
|
718
700
|
logger.info("Initiating tunnel restart", {
|
|
719
701
|
tunnelId: tunnelid,
|
|
720
|
-
configId: existingTunnel.
|
|
702
|
+
configId: existingTunnel.configId
|
|
721
703
|
});
|
|
722
704
|
try {
|
|
723
705
|
const tunnelName = existingTunnel.tunnelName;
|
|
724
|
-
const currentConfigId = existingTunnel.
|
|
706
|
+
const currentConfigId = existingTunnel.configId;
|
|
725
707
|
const currentConfig = existingTunnel.tunnelConfig;
|
|
726
|
-
const configWithForwarding = existingTunnel.configWithForwarding;
|
|
727
|
-
const additionalForwarding = existingTunnel.additionalForwarding;
|
|
728
708
|
const currentServe = existingTunnel.serve;
|
|
729
709
|
const autoReconnect = existingTunnel.autoReconnect || false;
|
|
730
710
|
this.tunnelsByTunnelId.delete(tunnelid);
|
|
731
|
-
this.tunnelsByConfigId.delete(existingTunnel.
|
|
711
|
+
this.tunnelsByConfigId.delete(existingTunnel.configId);
|
|
732
712
|
this.tunnelStats.delete(tunnelid);
|
|
733
713
|
this.tunnelStatsListeners.delete(tunnelid);
|
|
734
714
|
this.tunnelErrorListeners.delete(tunnelid);
|
|
715
|
+
this.tunnelPollingErrorListeners.delete(tunnelid);
|
|
735
716
|
this.tunnelDisconnectListeners.delete(tunnelid);
|
|
736
717
|
this.tunnelWorkerErrorListeners.delete(tunnelid);
|
|
737
718
|
this.tunnelStartListeners.delete(tunnelid);
|
|
@@ -740,12 +721,10 @@ var init_TunnelManager = __esm({
|
|
|
740
721
|
this.tunnelReconnectionCompletedListeners.delete(tunnelid);
|
|
741
722
|
this.tunnelReconnectionFailedListeners.delete(tunnelid);
|
|
742
723
|
const newTunnel = await this._createTunnelWithProcessedConfig({
|
|
743
|
-
|
|
724
|
+
configId: currentConfigId,
|
|
744
725
|
tunnelid,
|
|
745
726
|
tunnelName,
|
|
746
727
|
originalConfig: currentConfig,
|
|
747
|
-
configWithForwarding,
|
|
748
|
-
additionalForwarding,
|
|
749
728
|
serve: currentServe,
|
|
750
729
|
autoReconnect
|
|
751
730
|
});
|
|
@@ -774,20 +753,18 @@ var init_TunnelManager = __esm({
|
|
|
774
753
|
* @throws Error if the tunnel is not found or if the update process fails
|
|
775
754
|
*/
|
|
776
755
|
async updateConfig(newConfig) {
|
|
777
|
-
const {
|
|
778
|
-
if (!
|
|
779
|
-
throw new Error(`Invalid
|
|
756
|
+
const { configId, tunnelName: newTunnelName } = newConfig;
|
|
757
|
+
if (!configId || configId.trim().length === 0) {
|
|
758
|
+
throw new Error(`Invalid configId: "${configId}"`);
|
|
780
759
|
}
|
|
781
|
-
const existingTunnel = this.tunnelsByConfigId.get(
|
|
760
|
+
const existingTunnel = this.tunnelsByConfigId.get(configId);
|
|
782
761
|
if (!existingTunnel) {
|
|
783
|
-
throw new Error(`Tunnel with config id "${
|
|
762
|
+
throw new Error(`Tunnel with config id "${configId}" not found`);
|
|
784
763
|
}
|
|
785
764
|
const isStopped = existingTunnel.isStopped;
|
|
786
765
|
const currentTunnelConfig = existingTunnel.tunnelConfig;
|
|
787
|
-
const currentConfigWithForwarding = existingTunnel.configWithForwarding;
|
|
788
766
|
const currentTunnelId = existingTunnel.tunnelid;
|
|
789
|
-
const currentTunnelConfigId = existingTunnel.
|
|
790
|
-
const currentAdditionalForwarding = existingTunnel.additionalForwarding;
|
|
767
|
+
const currentTunnelConfigId = existingTunnel.configId;
|
|
791
768
|
const currentTunnelName = existingTunnel.tunnelName;
|
|
792
769
|
const currentServe = existingTunnel.serve;
|
|
793
770
|
const currentAutoReconnect = existingTunnel.autoReconnect || false;
|
|
@@ -799,22 +776,19 @@ var init_TunnelManager = __esm({
|
|
|
799
776
|
this.tunnelsByConfigId.delete(currentTunnelConfigId);
|
|
800
777
|
const mergedBaseConfig = {
|
|
801
778
|
...newConfig,
|
|
802
|
-
|
|
779
|
+
configId,
|
|
803
780
|
tunnelName: newTunnelName !== void 0 ? newTunnelName : currentTunnelName,
|
|
804
781
|
serve: newConfig.serve !== void 0 ? newConfig.serve : currentServe
|
|
805
782
|
};
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
);
|
|
783
|
+
const effectiveServe = newConfig.serve !== void 0 ? newConfig.serve : currentServe;
|
|
784
|
+
const effectiveTunnelName = newTunnelName !== void 0 ? newTunnelName : currentTunnelName;
|
|
785
|
+
let configWithForwarding;
|
|
810
786
|
const newTunnel = await this._createTunnelWithProcessedConfig({
|
|
811
|
-
|
|
787
|
+
configId,
|
|
812
788
|
tunnelid: currentTunnelId,
|
|
813
|
-
tunnelName:
|
|
789
|
+
tunnelName: effectiveTunnelName,
|
|
814
790
|
originalConfig: mergedBaseConfig,
|
|
815
|
-
|
|
816
|
-
additionalForwarding: additionalForwarding !== void 0 ? additionalForwarding : currentAdditionalForwarding,
|
|
817
|
-
serve: newConfig.serve !== void 0 ? newConfig.serve : currentServe,
|
|
791
|
+
serve: effectiveServe,
|
|
818
792
|
autoReconnect: currentAutoReconnect
|
|
819
793
|
});
|
|
820
794
|
if (!isStopped) {
|
|
@@ -822,23 +796,21 @@ var init_TunnelManager = __esm({
|
|
|
822
796
|
}
|
|
823
797
|
logger.info("Tunnel configuration updated", {
|
|
824
798
|
tunnelId: newTunnel.tunnelid,
|
|
825
|
-
configId: newTunnel.
|
|
799
|
+
configId: newTunnel.configId,
|
|
826
800
|
isStopped
|
|
827
801
|
});
|
|
828
802
|
return newTunnel;
|
|
829
803
|
} catch (error) {
|
|
830
804
|
logger.error("Error updating tunnel configuration", {
|
|
831
|
-
configId
|
|
805
|
+
configId,
|
|
832
806
|
error: error instanceof Error ? error.message : String(error)
|
|
833
807
|
});
|
|
834
808
|
try {
|
|
835
809
|
const originalTunnel = await this._createTunnelWithProcessedConfig({
|
|
836
|
-
|
|
810
|
+
configId: currentTunnelConfigId,
|
|
837
811
|
tunnelid: currentTunnelId,
|
|
838
812
|
tunnelName: currentTunnelName,
|
|
839
813
|
originalConfig: currentTunnelConfig,
|
|
840
|
-
configWithForwarding: currentConfigWithForwarding,
|
|
841
|
-
additionalForwarding: currentAdditionalForwarding,
|
|
842
814
|
serve: currentServe,
|
|
843
815
|
autoReconnect: currentAutoReconnect
|
|
844
816
|
});
|
|
@@ -954,6 +926,19 @@ var init_TunnelManager = __esm({
|
|
|
954
926
|
logger.info("Error listener registered for tunnel", { tunnelId, listenerId });
|
|
955
927
|
return listenerId;
|
|
956
928
|
}
|
|
929
|
+
async registerPollingErrorListener(tunnelId, listener) {
|
|
930
|
+
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
931
|
+
if (!managed) {
|
|
932
|
+
throw new Error(`Tunnel "${tunnelId}" not found`);
|
|
933
|
+
}
|
|
934
|
+
if (!this.tunnelPollingErrorListeners.has(tunnelId)) {
|
|
935
|
+
this.tunnelPollingErrorListeners.set(tunnelId, /* @__PURE__ */ new Map());
|
|
936
|
+
}
|
|
937
|
+
const listenerId = getRandomId();
|
|
938
|
+
this.tunnelPollingErrorListeners.get(tunnelId).set(listenerId, listener);
|
|
939
|
+
logger.info("Polling error listener registered for tunnel", { tunnelId, listenerId });
|
|
940
|
+
return listenerId;
|
|
941
|
+
}
|
|
957
942
|
async registerDisconnectListener(tunnelId, listener) {
|
|
958
943
|
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
959
944
|
if (!managed) {
|
|
@@ -1085,6 +1070,22 @@ var init_TunnelManager = __esm({
|
|
|
1085
1070
|
logger.warn("Attempted to deregister non-existent error listener", { tunnelId, listenerId });
|
|
1086
1071
|
}
|
|
1087
1072
|
}
|
|
1073
|
+
deregisterPollingErrorListener(tunnelId, listenerId) {
|
|
1074
|
+
const listeners = this.tunnelPollingErrorListeners.get(tunnelId);
|
|
1075
|
+
if (!listeners) {
|
|
1076
|
+
logger.warn("No polling error listeners found for tunnel", { tunnelId });
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
const removed = listeners.delete(listenerId);
|
|
1080
|
+
if (removed) {
|
|
1081
|
+
logger.info("Polling error listener deregistered", { tunnelId, listenerId });
|
|
1082
|
+
if (listeners.size === 0) {
|
|
1083
|
+
this.tunnelPollingErrorListeners.delete(tunnelId);
|
|
1084
|
+
}
|
|
1085
|
+
} else {
|
|
1086
|
+
logger.warn("Attempted to deregister non-existent polling error listener", { tunnelId, listenerId });
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1088
1089
|
deregisterDisconnectListener(tunnelId, listenerId) {
|
|
1089
1090
|
const listeners = this.tunnelDisconnectListeners.get(tunnelId);
|
|
1090
1091
|
if (!listeners) {
|
|
@@ -1202,6 +1203,38 @@ var init_TunnelManager = __esm({
|
|
|
1202
1203
|
logger.warn("Failed to set up stats callback", { tunnelId, error });
|
|
1203
1204
|
}
|
|
1204
1205
|
}
|
|
1206
|
+
setupTunnelPollingErrorCallback(tunnelId, managed) {
|
|
1207
|
+
try {
|
|
1208
|
+
const callback = ({ error }) => {
|
|
1209
|
+
try {
|
|
1210
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1211
|
+
logger.info("Tunnel reported polling error", { tunnelId, errorMessage });
|
|
1212
|
+
this.notifyPollingErrorListeners(tunnelId, errorMessage);
|
|
1213
|
+
} catch (e) {
|
|
1214
|
+
logger.warn("Error handling tunnel polling error callback", { tunnelId, e });
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
managed.instance.setPollingErrorCallback(callback);
|
|
1218
|
+
logger.debug("Tunnel polling error callback set up for tunnel", { tunnelId });
|
|
1219
|
+
} catch (error) {
|
|
1220
|
+
logger.warn("Failed to set up tunnel polling error callback", { tunnelId, error });
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
notifyPollingErrorListeners(tunnelId, errorMsg) {
|
|
1224
|
+
try {
|
|
1225
|
+
const listeners = this.tunnelPollingErrorListeners.get(tunnelId);
|
|
1226
|
+
if (!listeners) return;
|
|
1227
|
+
for (const [id, listener] of listeners) {
|
|
1228
|
+
try {
|
|
1229
|
+
listener(tunnelId, errorMsg);
|
|
1230
|
+
} catch (err) {
|
|
1231
|
+
logger.debug("Error in polling-error-listener callback", { listenerId: id, tunnelId, err });
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
} catch (err) {
|
|
1235
|
+
logger.debug("Failed to notify polling error listeners", { tunnelId, err });
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1205
1238
|
notifyErrorListeners(tunnelId, errorMsg, isFatal) {
|
|
1206
1239
|
try {
|
|
1207
1240
|
const listeners = this.tunnelErrorListeners.get(tunnelId);
|
|
@@ -1474,9 +1507,9 @@ var init_TunnelManager = __esm({
|
|
|
1474
1507
|
}
|
|
1475
1508
|
startStaticFileServer(managed) {
|
|
1476
1509
|
try {
|
|
1477
|
-
const
|
|
1478
|
-
const
|
|
1479
|
-
const fileServerWorkerPath = import_node_path.default.join(
|
|
1510
|
+
const __filename4 = (0, import_node_url.fileURLToPath)(importMetaUrl);
|
|
1511
|
+
const __dirname3 = import_node_path.default.dirname(__filename4);
|
|
1512
|
+
const fileServerWorkerPath = import_node_path.default.join(__dirname3, "workers", "file_serve_worker.cjs");
|
|
1480
1513
|
const staticServerWorker = new import_node_worker_threads.Worker(fileServerWorkerPath, {
|
|
1481
1514
|
workerData: {
|
|
1482
1515
|
dir: managed.serve,
|
|
@@ -1628,15 +1661,57 @@ var init_types = __esm({
|
|
|
1628
1661
|
});
|
|
1629
1662
|
|
|
1630
1663
|
// src/remote_management/remote_schema.ts
|
|
1664
|
+
function pinggyOptionsToTunnelConfigV1(opts, configStoredInCli) {
|
|
1665
|
+
const parsedTokens = opts.bearerTokenAuth ? Array.isArray(opts.bearerTokenAuth) ? opts.bearerTokenAuth : JSON.parse(opts.bearerTokenAuth) : [];
|
|
1666
|
+
return {
|
|
1667
|
+
version: configStoredInCli.version || "1.0",
|
|
1668
|
+
name: configStoredInCli.name || "",
|
|
1669
|
+
configId: configStoredInCli.configId || "",
|
|
1670
|
+
serverAddress: opts.serverAddress || "a.pinggy.io:443",
|
|
1671
|
+
token: opts.token || "",
|
|
1672
|
+
autoReconnect: opts.autoReconnect ?? true,
|
|
1673
|
+
force: opts.force ?? false,
|
|
1674
|
+
webDebugger: opts.webDebugger || "",
|
|
1675
|
+
forwarding: opts.forwarding ? opts.forwarding : "",
|
|
1676
|
+
ipWhitelist: opts.ipWhitelist ? Array.isArray(opts.ipWhitelist) ? opts.ipWhitelist : JSON.parse(opts.ipWhitelist) : [],
|
|
1677
|
+
basicAuth: opts.basicAuth && Object.keys(opts.basicAuth).length ? opts.basicAuth : void 0,
|
|
1678
|
+
bearerTokenAuth: parsedTokens.length ? parsedTokens : void 0,
|
|
1679
|
+
headerModification: opts.headerModification || [],
|
|
1680
|
+
reverseProxy: opts.reverseProxy ?? false,
|
|
1681
|
+
xForwardedFor: !!opts.xForwardedFor,
|
|
1682
|
+
httpsOnly: opts.httpsOnly ?? false,
|
|
1683
|
+
originalRequestUrl: opts.originalRequestUrl ?? false,
|
|
1684
|
+
allowPreflight: opts.allowPreflight ?? false,
|
|
1685
|
+
optional: opts.optional || {}
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1631
1688
|
function tunnelConfigToPinggyOptions(config) {
|
|
1689
|
+
const forwardingData = [];
|
|
1690
|
+
forwardingData.push({
|
|
1691
|
+
address: `${config.forwardedhost}:${config.localport}`,
|
|
1692
|
+
type: config.type || import_pinggy3.TunnelType.Http
|
|
1693
|
+
// Default to HTTP for the primary forwarding entry
|
|
1694
|
+
});
|
|
1695
|
+
if (config.additionalForwarding && Array.isArray(config.additionalForwarding)) {
|
|
1696
|
+
config.additionalForwarding.forEach((entry) => {
|
|
1697
|
+
if (entry.localDomain && entry.localPort && entry.remoteDomain) {
|
|
1698
|
+
const listenAddress = entry.remotePort && isValidPort(entry.remotePort) ? `${entry.remoteDomain}:${entry.remotePort}` : entry.remoteDomain;
|
|
1699
|
+
forwardingData.push({
|
|
1700
|
+
address: `${entry.localDomain}:${entry.localPort}`,
|
|
1701
|
+
listenAddress,
|
|
1702
|
+
type: import_pinggy3.TunnelType.Http
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1632
1707
|
return {
|
|
1633
1708
|
token: config.token || "",
|
|
1634
1709
|
serverAddress: config.serveraddress || "free.pinggy.io",
|
|
1635
|
-
forwarding:
|
|
1710
|
+
forwarding: forwardingData,
|
|
1636
1711
|
webDebugger: config.webdebuggerport ? `localhost:${config.webdebuggerport}` : "",
|
|
1637
1712
|
ipWhitelist: config.ipwhitelist || [],
|
|
1638
1713
|
basicAuth: config.basicauth ? config.basicauth : [],
|
|
1639
|
-
bearerTokenAuth: config.bearerauth
|
|
1714
|
+
bearerTokenAuth: config.bearerauth || [],
|
|
1640
1715
|
headerModification: config.headermodification,
|
|
1641
1716
|
xForwardedFor: !!config.xff,
|
|
1642
1717
|
httpsOnly: config.httpsOnly,
|
|
@@ -1650,18 +1725,38 @@ function tunnelConfigToPinggyOptions(config) {
|
|
|
1650
1725
|
}
|
|
1651
1726
|
};
|
|
1652
1727
|
}
|
|
1653
|
-
function pinggyOptionsToTunnelConfig(opts, configid, configName, localserverTls, greetMsg,
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1728
|
+
function pinggyOptionsToTunnelConfig(opts, configid, configName, localserverTls, greetMsg, serve) {
|
|
1729
|
+
let primaryEntry;
|
|
1730
|
+
let additionalEntries = [];
|
|
1731
|
+
if (Array.isArray(opts.forwarding)) {
|
|
1732
|
+
primaryEntry = opts.forwarding.find((e) => !e.listenAddress) ?? opts.forwarding[0];
|
|
1733
|
+
additionalEntries = opts.forwarding.filter(
|
|
1734
|
+
(e) => e !== primaryEntry && Boolean(e.listenAddress)
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1737
|
+
const forwarding = primaryEntry ? String(primaryEntry.address) : String(opts.forwarding);
|
|
1738
|
+
const [parsedForwardedHost, portStr] = forwarding.split(":");
|
|
1739
|
+
const parsedLocalPort = parseInt(portStr, 10);
|
|
1740
|
+
const tunnelType = primaryEntry?.type ?? import_pinggy3.TunnelType.Http;
|
|
1741
|
+
const additionalForwarding = additionalEntries.map((e) => {
|
|
1742
|
+
const [localDomain, localPortStr] = String(e.address).split(":");
|
|
1743
|
+
const [remoteDomain, remotePortStr] = String(e.listenAddress).split(":");
|
|
1744
|
+
const localPort = parseInt(localPortStr, 10);
|
|
1745
|
+
const remotePort = parseInt(remotePortStr, 10);
|
|
1746
|
+
return {
|
|
1747
|
+
localDomain,
|
|
1748
|
+
localPort: isNaN(localPort) ? 0 : localPort,
|
|
1749
|
+
remoteDomain,
|
|
1750
|
+
remotePort: isNaN(remotePort) ? 0 : remotePort
|
|
1751
|
+
};
|
|
1752
|
+
});
|
|
1658
1753
|
const parsedTokens = opts.bearerTokenAuth ? Array.isArray(opts.bearerTokenAuth) ? opts.bearerTokenAuth : JSON.parse(opts.bearerTokenAuth) : [];
|
|
1659
1754
|
return {
|
|
1660
1755
|
allowPreflight: opts.allowPreflight ?? false,
|
|
1661
1756
|
allowpreflight: opts.allowPreflight ?? false,
|
|
1662
1757
|
autoreconnect: opts.autoReconnect ?? false,
|
|
1663
1758
|
basicauth: opts.basicAuth && Object.keys(opts.basicAuth).length ? opts.basicAuth : null,
|
|
1664
|
-
bearerauth: parsedTokens.length ? parsedTokens.join(",") : null,
|
|
1759
|
+
bearerauth: parsedTokens.length ? [parsedTokens.join(",")] : null,
|
|
1665
1760
|
configid,
|
|
1666
1761
|
configname: configName,
|
|
1667
1762
|
greetmsg: greetMsg || "",
|
|
@@ -1690,16 +1785,17 @@ function pinggyOptionsToTunnelConfig(opts, configid, configName, localserverTls,
|
|
|
1690
1785
|
serve: serve || ""
|
|
1691
1786
|
};
|
|
1692
1787
|
}
|
|
1693
|
-
var import_pinggy3, import_zod, HeaderModificationSchema, AdditionalForwardingSchema, TunnelConfigSchema, StartSchema, StopSchema, GetSchema, RestartSchema, UpdateConfigSchema;
|
|
1788
|
+
var import_pinggy3, import_zod, HeaderModificationSchema, AdditionalForwardingSchema, TunnelConfigSchema, StartSchema, StopSchema, GetSchema, RestartSchema, UpdateConfigSchema, ForwardingEntryV2Schema, TunnelConfigV1Schema, StartV2Schema, UpdateConfigV2Schema;
|
|
1694
1789
|
var init_remote_schema = __esm({
|
|
1695
1790
|
"src/remote_management/remote_schema.ts"() {
|
|
1696
1791
|
"use strict";
|
|
1697
1792
|
init_cjs_shims();
|
|
1698
1793
|
import_pinggy3 = require("@pinggy/pinggy");
|
|
1699
1794
|
import_zod = require("zod");
|
|
1795
|
+
init_util();
|
|
1700
1796
|
HeaderModificationSchema = import_zod.z.object({
|
|
1701
1797
|
key: import_zod.z.string(),
|
|
1702
|
-
value: import_zod.z.array(import_zod.z.string()).optional(),
|
|
1798
|
+
value: import_zod.z.array(import_zod.z.string()).nullable().optional(),
|
|
1703
1799
|
type: import_zod.z.enum(["add", "remove", "update"])
|
|
1704
1800
|
});
|
|
1705
1801
|
AdditionalForwardingSchema = import_zod.z.object({
|
|
@@ -1715,7 +1811,7 @@ var init_remote_schema = __esm({
|
|
|
1715
1811
|
// legacy key
|
|
1716
1812
|
autoreconnect: import_zod.z.boolean(),
|
|
1717
1813
|
basicauth: import_zod.z.array(import_zod.z.object({ username: import_zod.z.string(), password: import_zod.z.string() })).nullable(),
|
|
1718
|
-
bearerauth: import_zod.z.string().nullable(),
|
|
1814
|
+
bearerauth: import_zod.z.array(import_zod.z.string()).nullable(),
|
|
1719
1815
|
configid: import_zod.z.string(),
|
|
1720
1816
|
configname: import_zod.z.string(),
|
|
1721
1817
|
greetmsg: import_zod.z.string().optional(),
|
|
@@ -1772,11 +1868,56 @@ var init_remote_schema = __esm({
|
|
|
1772
1868
|
UpdateConfigSchema = import_zod.z.object({
|
|
1773
1869
|
tunnelConfig: TunnelConfigSchema
|
|
1774
1870
|
});
|
|
1871
|
+
ForwardingEntryV2Schema = import_zod.z.object({
|
|
1872
|
+
listenAddress: import_zod.z.string().optional(),
|
|
1873
|
+
address: import_zod.z.string(),
|
|
1874
|
+
type: import_zod.z.enum([import_pinggy3.TunnelType.Http, import_pinggy3.TunnelType.Tcp, import_pinggy3.TunnelType.Udp, import_pinggy3.TunnelType.Tls, import_pinggy3.TunnelType.TlsTcp]).optional()
|
|
1875
|
+
});
|
|
1876
|
+
TunnelConfigV1Schema = import_zod.z.object({
|
|
1877
|
+
// Meta Info
|
|
1878
|
+
version: import_zod.z.string(),
|
|
1879
|
+
name: import_zod.z.string(),
|
|
1880
|
+
configId: import_zod.z.string(),
|
|
1881
|
+
// General tunnel configurations
|
|
1882
|
+
serverAddress: import_zod.z.string().optional(),
|
|
1883
|
+
token: import_zod.z.string().optional(),
|
|
1884
|
+
autoReconnect: import_zod.z.boolean().optional(),
|
|
1885
|
+
reconnectInterval: import_zod.z.number().optional(),
|
|
1886
|
+
maxReconnectAttempts: import_zod.z.number().optional(),
|
|
1887
|
+
force: import_zod.z.boolean(),
|
|
1888
|
+
keepAliveInterval: import_zod.z.number().optional(),
|
|
1889
|
+
webDebugger: import_zod.z.string(),
|
|
1890
|
+
//Forwarding
|
|
1891
|
+
// Either a URL string (e.g. "https://localhost:5555") or an array of forwarding entries.
|
|
1892
|
+
forwarding: import_zod.z.union([
|
|
1893
|
+
import_zod.z.string(),
|
|
1894
|
+
import_zod.z.array(ForwardingEntryV2Schema)
|
|
1895
|
+
]),
|
|
1896
|
+
// IP whitelist
|
|
1897
|
+
ipWhitelist: import_zod.z.array(import_zod.z.string()).optional(),
|
|
1898
|
+
basicAuth: import_zod.z.array(import_zod.z.object({ username: import_zod.z.string(), password: import_zod.z.string() })).optional(),
|
|
1899
|
+
bearerTokenAuth: import_zod.z.array(import_zod.z.string()).optional(),
|
|
1900
|
+
headerModification: import_zod.z.array(HeaderModificationSchema).optional(),
|
|
1901
|
+
reverseProxy: import_zod.z.boolean().optional(),
|
|
1902
|
+
xForwardedFor: import_zod.z.boolean().optional(),
|
|
1903
|
+
httpsOnly: import_zod.z.boolean().optional(),
|
|
1904
|
+
originalRequestUrl: import_zod.z.boolean().optional(),
|
|
1905
|
+
allowPreflight: import_zod.z.boolean().optional(),
|
|
1906
|
+
serve: import_zod.z.string().optional(),
|
|
1907
|
+
optional: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
|
|
1908
|
+
});
|
|
1909
|
+
StartV2Schema = import_zod.z.object({
|
|
1910
|
+
tunnelID: import_zod.z.string().nullable().optional(),
|
|
1911
|
+
tunnelConfig: TunnelConfigV1Schema
|
|
1912
|
+
});
|
|
1913
|
+
UpdateConfigV2Schema = import_zod.z.object({
|
|
1914
|
+
tunnelConfig: TunnelConfigV1Schema
|
|
1915
|
+
});
|
|
1775
1916
|
}
|
|
1776
1917
|
});
|
|
1777
1918
|
|
|
1778
1919
|
// src/remote_management/handler.ts
|
|
1779
|
-
var
|
|
1920
|
+
var TunnelOperations;
|
|
1780
1921
|
var init_handler = __esm({
|
|
1781
1922
|
"src/remote_management/handler.ts"() {
|
|
1782
1923
|
"use strict";
|
|
@@ -1784,7 +1925,6 @@ var init_handler = __esm({
|
|
|
1784
1925
|
init_types();
|
|
1785
1926
|
init_TunnelManager();
|
|
1786
1927
|
init_remote_schema();
|
|
1787
|
-
import_pinggy4 = require("@pinggy/pinggy");
|
|
1788
1928
|
TunnelOperations = class {
|
|
1789
1929
|
constructor() {
|
|
1790
1930
|
this.tunnelManager = TunnelManager.getInstance();
|
|
@@ -1803,7 +1943,7 @@ var init_handler = __esm({
|
|
|
1803
1943
|
return status;
|
|
1804
1944
|
}
|
|
1805
1945
|
// --- Helper to construct TunnelResponse ---
|
|
1806
|
-
async buildTunnelResponse(tunnelid, tunnelConfig, configid, tunnelName,
|
|
1946
|
+
async buildTunnelResponse(tunnelid, tunnelConfig, configid, tunnelName, serve) {
|
|
1807
1947
|
const [status, stats, tlsInfo, greetMsg, remoteurls] = await Promise.all([
|
|
1808
1948
|
this.tunnelManager.getTunnelStatus(tunnelid),
|
|
1809
1949
|
this.tunnelManager.getLatestTunnelStats(tunnelid) || newStats(),
|
|
@@ -1814,11 +1954,27 @@ var init_handler = __esm({
|
|
|
1814
1954
|
return {
|
|
1815
1955
|
tunnelid,
|
|
1816
1956
|
remoteurls,
|
|
1817
|
-
tunnelconfig: pinggyOptionsToTunnelConfig(tunnelConfig, configid, tunnelName, tlsInfo, greetMsg
|
|
1957
|
+
tunnelconfig: pinggyOptionsToTunnelConfig(tunnelConfig, configid, tunnelName, tlsInfo, greetMsg),
|
|
1818
1958
|
status: this.buildStatus(tunnelid, status, "" /* NoError */),
|
|
1819
1959
|
stats
|
|
1820
1960
|
};
|
|
1821
1961
|
}
|
|
1962
|
+
async buildTunnelResponseV2(tunnelid, tunnelConfig, configFromCli, configid, tunnelName, serve) {
|
|
1963
|
+
const [status, stats, greetMsg, remoteurls] = await Promise.all([
|
|
1964
|
+
this.tunnelManager.getTunnelStatus(tunnelid),
|
|
1965
|
+
this.tunnelManager.getLatestTunnelStats(tunnelid) || newStats(),
|
|
1966
|
+
this.tunnelManager.getTunnelGreetMessage(tunnelid),
|
|
1967
|
+
this.tunnelManager.getTunnelUrls(tunnelid)
|
|
1968
|
+
]);
|
|
1969
|
+
return {
|
|
1970
|
+
tunnelid,
|
|
1971
|
+
remoteurls,
|
|
1972
|
+
tunnelconfig: pinggyOptionsToTunnelConfigV1(tunnelConfig, configFromCli),
|
|
1973
|
+
status: this.buildStatus(tunnelid, status, "" /* NoError */),
|
|
1974
|
+
stats,
|
|
1975
|
+
greetmsg: greetMsg
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1822
1978
|
error(code, err, fallback) {
|
|
1823
1979
|
return newErrorResponse({
|
|
1824
1980
|
code,
|
|
@@ -1829,19 +1985,28 @@ var init_handler = __esm({
|
|
|
1829
1985
|
async handleStart(config) {
|
|
1830
1986
|
try {
|
|
1831
1987
|
const opts = tunnelConfigToPinggyOptions(config);
|
|
1832
|
-
const
|
|
1833
|
-
const { tunnelid, instance, tunnelName, additionalForwarding, serve } = await this.tunnelManager.createTunnel({
|
|
1988
|
+
const { tunnelid, instance, tunnelName, serve, tunnelConfig } = await this.tunnelManager.createTunnel({
|
|
1834
1989
|
...opts,
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
serve: config.serve
|
|
1990
|
+
configId: config.configid,
|
|
1991
|
+
name: config.configname,
|
|
1992
|
+
optional: {
|
|
1993
|
+
serve: config.serve
|
|
1994
|
+
}
|
|
1841
1995
|
});
|
|
1842
|
-
this.tunnelManager.startTunnel(tunnelid);
|
|
1996
|
+
await this.tunnelManager.startTunnel(tunnelid);
|
|
1997
|
+
const tunnelPconfig = await this.tunnelManager.getTunnelConfig("", tunnelid);
|
|
1998
|
+
const resp = this.buildTunnelResponse(tunnelid, tunnelPconfig, config.configid, tunnelName, serve);
|
|
1999
|
+
return resp;
|
|
2000
|
+
} catch (err) {
|
|
2001
|
+
return this.error(ErrorCode.ErrorStartingTunnel, err, "Unknown error occurred while starting tunnel");
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
async handleStartV2(config) {
|
|
2005
|
+
try {
|
|
2006
|
+
const { tunnelid, instance, serve } = await this.tunnelManager.createTunnel(config);
|
|
2007
|
+
await this.tunnelManager.startTunnel(tunnelid);
|
|
1843
2008
|
const tunnelPconfig = await this.tunnelManager.getTunnelConfig("", tunnelid);
|
|
1844
|
-
const resp = this.
|
|
2009
|
+
const resp = this.buildTunnelResponseV2(tunnelid, tunnelPconfig, config, config.configId, config.name, config.serve);
|
|
1845
2010
|
return resp;
|
|
1846
2011
|
} catch (err) {
|
|
1847
2012
|
return this.error(ErrorCode.ErrorStartingTunnel, err, "Unknown error occurred while starting tunnel");
|
|
@@ -1852,20 +2017,59 @@ var init_handler = __esm({
|
|
|
1852
2017
|
const opts = tunnelConfigToPinggyOptions(config);
|
|
1853
2018
|
const tunnel = await this.tunnelManager.updateConfig({
|
|
1854
2019
|
...opts,
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
serve: config.serve
|
|
2020
|
+
configId: config.configid,
|
|
2021
|
+
name: config.configname,
|
|
2022
|
+
optional: {
|
|
2023
|
+
serve: config.serve
|
|
2024
|
+
}
|
|
1861
2025
|
});
|
|
1862
2026
|
if (!tunnel.instance || !tunnel.tunnelConfig)
|
|
1863
2027
|
throw new Error("Invalid tunnel state after configuration update");
|
|
1864
|
-
return this.buildTunnelResponse(tunnel.tunnelid, tunnel.tunnelConfig, config.configid, tunnel.tunnelName, tunnel.
|
|
2028
|
+
return this.buildTunnelResponse(tunnel.tunnelid, tunnel.tunnelConfig, config.configid, tunnel.tunnelName, tunnel.serve);
|
|
1865
2029
|
} catch (err) {
|
|
1866
2030
|
return this.error(ErrorCode.InternalServerError, err, "Failed to update tunnel configuration");
|
|
1867
2031
|
}
|
|
1868
2032
|
}
|
|
2033
|
+
async handleUpdateConfigV2(config) {
|
|
2034
|
+
try {
|
|
2035
|
+
const tunnel = await this.tunnelManager.updateConfig(config);
|
|
2036
|
+
if (!tunnel.instance || !tunnel.tunnelConfig)
|
|
2037
|
+
throw new Error("Invalid tunnel state after configuration update");
|
|
2038
|
+
return this.buildTunnelResponseV2(tunnel.tunnelid, tunnel.tunnelConfig, config, config.configId, tunnel.tunnelName, tunnel.serve);
|
|
2039
|
+
} catch (err) {
|
|
2040
|
+
return this.error(ErrorCode.InternalServerError, err, "Failed to update tunnel configuration");
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
async handleListV2() {
|
|
2044
|
+
try {
|
|
2045
|
+
const tunnels = await this.tunnelManager.getAllTunnels();
|
|
2046
|
+
if (tunnels.length === 0) {
|
|
2047
|
+
return [];
|
|
2048
|
+
}
|
|
2049
|
+
return Promise.all(
|
|
2050
|
+
tunnels.map(async (t) => {
|
|
2051
|
+
const rawStats = this.tunnelManager.getLatestTunnelStats(t.tunnelid) || newStats();
|
|
2052
|
+
const [status, tlsInfo, greetMsg] = await Promise.all([
|
|
2053
|
+
this.tunnelManager.getTunnelStatus(t.tunnelid),
|
|
2054
|
+
this.tunnelManager.getLocalserverTlsInfo(t.tunnelid),
|
|
2055
|
+
this.tunnelManager.getTunnelGreetMessage(t.tunnelid)
|
|
2056
|
+
]);
|
|
2057
|
+
const tunnelConfguration = status !== "closed" /* Closed */ && status !== "exited" /* Exited */ ? await this.tunnelManager.getTunnelConfig("", t.tunnelid) : t.tunnelConfig;
|
|
2058
|
+
const tunnelConfig = pinggyOptionsToTunnelConfigV1(tunnelConfguration, t.tunnelConfig);
|
|
2059
|
+
return {
|
|
2060
|
+
tunnelid: t.tunnelid,
|
|
2061
|
+
remoteurls: t.remoteurls,
|
|
2062
|
+
status: this.buildStatus(t.tunnelid, status, "" /* NoError */),
|
|
2063
|
+
stats: rawStats,
|
|
2064
|
+
tunnelconfig: tunnelConfig,
|
|
2065
|
+
greetmsg: greetMsg
|
|
2066
|
+
};
|
|
2067
|
+
})
|
|
2068
|
+
);
|
|
2069
|
+
} catch (err) {
|
|
2070
|
+
return this.error(ErrorCode.InternalServerError, err, "Failed to list tunnels");
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
1869
2073
|
async handleList() {
|
|
1870
2074
|
try {
|
|
1871
2075
|
const tunnels = await this.tunnelManager.getAllTunnels();
|
|
@@ -1881,7 +2085,7 @@ var init_handler = __esm({
|
|
|
1881
2085
|
this.tunnelManager.getTunnelGreetMessage(t.tunnelid)
|
|
1882
2086
|
]);
|
|
1883
2087
|
const pinggyOptions = status !== "closed" /* Closed */ && status !== "exited" /* Exited */ ? await this.tunnelManager.getTunnelConfig("", t.tunnelid) : t.tunnelConfig;
|
|
1884
|
-
const tunnelConfig = pinggyOptionsToTunnelConfig(pinggyOptions, t.
|
|
2088
|
+
const tunnelConfig = pinggyOptionsToTunnelConfig(pinggyOptions, t.configId, t.tunnelName, tlsInfo, greetMsg, t.serve);
|
|
1885
2089
|
return {
|
|
1886
2090
|
tunnelid: t.tunnelid,
|
|
1887
2091
|
remoteurls: t.remoteurls,
|
|
@@ -1897,10 +2101,10 @@ var init_handler = __esm({
|
|
|
1897
2101
|
}
|
|
1898
2102
|
async handleStop(tunnelid) {
|
|
1899
2103
|
try {
|
|
1900
|
-
const {
|
|
2104
|
+
const { configId } = this.tunnelManager.stopTunnel(tunnelid);
|
|
1901
2105
|
const managed = this.tunnelManager.getManagedTunnel("", tunnelid);
|
|
1902
2106
|
if (!managed?.tunnelConfig) throw new Error(`Tunnel config for ID "${tunnelid}" not found`);
|
|
1903
|
-
return this.buildTunnelResponse(tunnelid, managed.tunnelConfig,
|
|
2107
|
+
return this.buildTunnelResponse(tunnelid, managed.tunnelConfig, configId, managed.tunnelName, managed.serve);
|
|
1904
2108
|
} catch (err) {
|
|
1905
2109
|
return this.error(ErrorCode.TunnelNotFound, err, "Failed to stop tunnel");
|
|
1906
2110
|
}
|
|
@@ -1909,7 +2113,7 @@ var init_handler = __esm({
|
|
|
1909
2113
|
try {
|
|
1910
2114
|
const managed = this.tunnelManager.getManagedTunnel("", tunnelid);
|
|
1911
2115
|
if (!managed?.tunnelConfig) throw new Error(`Tunnel config for ID "${tunnelid}" not found`);
|
|
1912
|
-
return this.buildTunnelResponse(tunnelid, managed.tunnelConfig, managed.
|
|
2116
|
+
return this.buildTunnelResponse(tunnelid, managed.tunnelConfig, managed.configId, managed.tunnelName, managed.serve);
|
|
1913
2117
|
} catch (err) {
|
|
1914
2118
|
return this.error(ErrorCode.TunnelNotFound, err, "Failed to get tunnel information");
|
|
1915
2119
|
}
|
|
@@ -1919,7 +2123,7 @@ var init_handler = __esm({
|
|
|
1919
2123
|
await this.tunnelManager.restartTunnel(tunnelid);
|
|
1920
2124
|
const managed = this.tunnelManager.getManagedTunnel("", tunnelid);
|
|
1921
2125
|
if (!managed?.tunnelConfig) throw new Error(`Tunnel config for ID "${tunnelid}" not found`);
|
|
1922
|
-
return this.buildTunnelResponse(tunnelid, managed.tunnelConfig, managed.
|
|
2126
|
+
return this.buildTunnelResponse(tunnelid, managed.tunnelConfig, managed.configId, managed.tunnelName, managed.serve);
|
|
1923
2127
|
} catch (err) {
|
|
1924
2128
|
return this.error(ErrorCode.TunnelNotFound, err, "Failed to restart tunnel");
|
|
1925
2129
|
}
|
|
@@ -1962,7 +2166,216 @@ var init_handler = __esm({
|
|
|
1962
2166
|
}
|
|
1963
2167
|
});
|
|
1964
2168
|
|
|
2169
|
+
// src/remote_management/websocket_printer.ts
|
|
2170
|
+
var import_picocolors3, PENDING_START_TIMEOUT_MS, RemoteManagementWebSocketPrinter, remoteManagementWebSocketPrinter;
|
|
2171
|
+
var init_websocket_printer = __esm({
|
|
2172
|
+
"src/remote_management/websocket_printer.ts"() {
|
|
2173
|
+
"use strict";
|
|
2174
|
+
init_cjs_shims();
|
|
2175
|
+
init_logger();
|
|
2176
|
+
init_TunnelManager();
|
|
2177
|
+
init_types();
|
|
2178
|
+
init_printer();
|
|
2179
|
+
import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
2180
|
+
PENDING_START_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
2181
|
+
RemoteManagementWebSocketPrinter = class {
|
|
2182
|
+
constructor() {
|
|
2183
|
+
this.tunnelManager = TunnelManager.getInstance();
|
|
2184
|
+
this.pendingStarts = /* @__PURE__ */ new Map();
|
|
2185
|
+
}
|
|
2186
|
+
setTunnelHandler(tunnelHandler) {
|
|
2187
|
+
this.tunnelHandler = tunnelHandler;
|
|
2188
|
+
}
|
|
2189
|
+
queueStart(config) {
|
|
2190
|
+
this.cleanupExpiredPendingStarts();
|
|
2191
|
+
const entry = {
|
|
2192
|
+
configId: this.getConfigIdFromRequest(config),
|
|
2193
|
+
configName: this.getConfigNameFromRequest(config),
|
|
2194
|
+
queuedAt: Date.now()
|
|
2195
|
+
};
|
|
2196
|
+
this.latestPendingConfigId = entry.configId;
|
|
2197
|
+
this.pendingStarts.set(entry.configId, entry);
|
|
2198
|
+
printer_default.startSpinner("Starting tunnel with config name: " + entry.configName);
|
|
2199
|
+
}
|
|
2200
|
+
failQueuedStart(config, reason) {
|
|
2201
|
+
const configId = this.getConfigIdFromRequest(config);
|
|
2202
|
+
const pending = this.pendingStarts.get(configId);
|
|
2203
|
+
const configName = pending?.configName || this.getConfigNameFromRequest(config);
|
|
2204
|
+
this.pendingStarts.delete(configId);
|
|
2205
|
+
if (this.latestPendingConfigId === configId) {
|
|
2206
|
+
this.latestPendingConfigId = void 0;
|
|
2207
|
+
printer_default.stopSpinnerFail(`Failed to start tunnel with config name: ${configName}. ${reason}`);
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
handleStartResult(config, result) {
|
|
2211
|
+
this.cleanupExpiredPendingStarts();
|
|
2212
|
+
const requestedConfigId = this.getConfigIdFromRequest(config);
|
|
2213
|
+
if (this.latestPendingConfigId && requestedConfigId !== this.latestPendingConfigId) {
|
|
2214
|
+
this.pendingStarts.delete(requestedConfigId);
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
if (isErrorResponse(result)) {
|
|
2218
|
+
this.failQueuedStart(config, result.message);
|
|
2219
|
+
return;
|
|
2220
|
+
}
|
|
2221
|
+
const configId = this.getConfigIdFromTunnel(result);
|
|
2222
|
+
const pending = this.pendingStarts.get(requestedConfigId) || {
|
|
2223
|
+
configId: requestedConfigId,
|
|
2224
|
+
configName: this.getConfigNameFromRequest(config),
|
|
2225
|
+
queuedAt: Date.now()
|
|
2226
|
+
};
|
|
2227
|
+
pending.tunnelId = result.tunnelid;
|
|
2228
|
+
this.pendingStarts.set(requestedConfigId, pending);
|
|
2229
|
+
if (result.remoteurls.length > 0) {
|
|
2230
|
+
this.completePendingStart(pending, result.remoteurls);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
printStopRequested(tunnelId) {
|
|
2234
|
+
const details = this.resolveTunnelDetails(tunnelId);
|
|
2235
|
+
printer_default.startSpinner("Stopping tunnel with config name: " + details.configName);
|
|
2236
|
+
}
|
|
2237
|
+
handleStopResult(tunnelId, result) {
|
|
2238
|
+
const details = this.resolveTunnelDetails(tunnelId, result);
|
|
2239
|
+
if (isErrorResponse(result)) {
|
|
2240
|
+
printer_default.stopSpinnerFail("Failed to stop tunnel with config name: " + details.configName);
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2243
|
+
this.pendingStarts.delete(details.configId);
|
|
2244
|
+
printer_default.stopSpinnerSuccess("Stopped tunnel with config name: " + details.configName);
|
|
2245
|
+
}
|
|
2246
|
+
printRestartRequested(tunnelId) {
|
|
2247
|
+
const details = this.resolveTunnelDetails(tunnelId);
|
|
2248
|
+
printer_default.startSpinner("Restarting tunnel with config name: " + details.configName);
|
|
2249
|
+
}
|
|
2250
|
+
handleRestartResult(tunnelId, result) {
|
|
2251
|
+
const details = this.resolveTunnelDetails(tunnelId, result);
|
|
2252
|
+
if (isErrorResponse(result)) {
|
|
2253
|
+
printer_default.warn(`Failed to restart tunnel with config name: ${details.configName}. ${result.message}`);
|
|
2254
|
+
printer_default.stopSpinnerFail("Failed to restart tunnel with config name: " + details.configName);
|
|
2255
|
+
return;
|
|
2256
|
+
}
|
|
2257
|
+
printer_default.stopSpinnerSuccess("Restarted tunnel with config name: " + details.configName);
|
|
2258
|
+
if (result.remoteurls?.length > 0) {
|
|
2259
|
+
printer_default.info(import_picocolors3.default.cyanBright("Remote URLs:"));
|
|
2260
|
+
(result.remoteurls ?? []).forEach(
|
|
2261
|
+
(url) => printer_default.print(" " + import_picocolors3.default.magentaBright(url))
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
monitorList(result) {
|
|
2266
|
+
this.cleanupExpiredPendingStarts();
|
|
2267
|
+
if (!Array.isArray(result) || this.pendingStarts.size === 0 || !this.latestPendingConfigId) {
|
|
2268
|
+
return;
|
|
2269
|
+
}
|
|
2270
|
+
for (const tunnel of result) {
|
|
2271
|
+
const pending = this.findPendingStart(tunnel);
|
|
2272
|
+
if (!pending) {
|
|
2273
|
+
continue;
|
|
2274
|
+
}
|
|
2275
|
+
if (pending.configId !== this.latestPendingConfigId) {
|
|
2276
|
+
continue;
|
|
2277
|
+
}
|
|
2278
|
+
pending.tunnelId = tunnel.tunnelid;
|
|
2279
|
+
this.pendingStarts.set(pending.configId, pending);
|
|
2280
|
+
if (tunnel.remoteurls.length > 0) {
|
|
2281
|
+
this.completePendingStart(pending, tunnel.remoteurls);
|
|
2282
|
+
continue;
|
|
2283
|
+
}
|
|
2284
|
+
if (tunnel.status.state === "exited" /* Exited */) {
|
|
2285
|
+
const reason = tunnel.status.errormsg || "Tunnel exited before a public URL was assigned";
|
|
2286
|
+
this.pendingStarts.delete(pending.configId);
|
|
2287
|
+
this.latestPendingConfigId = void 0;
|
|
2288
|
+
printer_default.stopSpinnerFail(`Tunnel start did not complete for config name: ${pending.configName}. ${reason}`);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
completePendingStart(entry, urls) {
|
|
2293
|
+
if (this.latestPendingConfigId && entry.configId !== this.latestPendingConfigId) {
|
|
2294
|
+
this.pendingStarts.delete(entry.configId);
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
this.pendingStarts.delete(entry.configId);
|
|
2298
|
+
this.latestPendingConfigId = void 0;
|
|
2299
|
+
printer_default.stopSpinnerSuccess(`Tunnel started with config name: ${entry.configName}.`);
|
|
2300
|
+
printer_default.info(import_picocolors3.default.cyanBright("Remote URLs:"));
|
|
2301
|
+
(urls ?? []).forEach(
|
|
2302
|
+
(url) => printer_default.print(" " + import_picocolors3.default.magentaBright(url))
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
cleanupExpiredPendingStarts() {
|
|
2306
|
+
const now = Date.now();
|
|
2307
|
+
for (const [configId, entry] of this.pendingStarts.entries()) {
|
|
2308
|
+
if (now - entry.queuedAt <= PENDING_START_TIMEOUT_MS) {
|
|
2309
|
+
continue;
|
|
2310
|
+
}
|
|
2311
|
+
this.pendingStarts.delete(configId);
|
|
2312
|
+
printer_default.warn(`Timed out while waiting for tunnel URL for config name: ${entry.configName}`);
|
|
2313
|
+
logger.warn("Pending websocket start entry expired", { configId, tunnelId: entry.tunnelId });
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
findPendingStart(tunnel) {
|
|
2317
|
+
const configId = this.getConfigIdFromTunnel(tunnel);
|
|
2318
|
+
const byConfigId = this.pendingStarts.get(configId);
|
|
2319
|
+
if (byConfigId) {
|
|
2320
|
+
return byConfigId;
|
|
2321
|
+
}
|
|
2322
|
+
for (const entry of this.pendingStarts.values()) {
|
|
2323
|
+
if (entry.tunnelId === tunnel.tunnelid) {
|
|
2324
|
+
return entry;
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
return void 0;
|
|
2328
|
+
}
|
|
2329
|
+
resolveTunnelDetails(tunnelId, result) {
|
|
2330
|
+
try {
|
|
2331
|
+
const managed = this.tunnelManager.getManagedTunnel(void 0, tunnelId);
|
|
2332
|
+
return {
|
|
2333
|
+
configId: managed.configId,
|
|
2334
|
+
configName: managed.tunnelName || managed.configId || tunnelId
|
|
2335
|
+
};
|
|
2336
|
+
} catch {
|
|
2337
|
+
if (result && !isErrorResponse(result)) {
|
|
2338
|
+
return {
|
|
2339
|
+
configId: this.getConfigIdFromTunnel(result),
|
|
2340
|
+
configName: this.getConfigNameFromTunnel(result)
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
return {
|
|
2344
|
+
configId: tunnelId,
|
|
2345
|
+
configName: tunnelId
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
getConfigIdFromRequest(config) {
|
|
2350
|
+
return "configid" in config ? config.configid : config.configId;
|
|
2351
|
+
}
|
|
2352
|
+
getConfigNameFromRequest(config) {
|
|
2353
|
+
return "configname" in config ? config.configname : config.name;
|
|
2354
|
+
}
|
|
2355
|
+
getConfigIdFromTunnel(tunnel) {
|
|
2356
|
+
return "configid" in tunnel.tunnelconfig ? tunnel.tunnelconfig.configid : tunnel.tunnelconfig.configId;
|
|
2357
|
+
}
|
|
2358
|
+
getConfigNameFromTunnel(tunnel) {
|
|
2359
|
+
return "configname" in tunnel.tunnelconfig ? tunnel.tunnelconfig.configname : tunnel.tunnelconfig.name;
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2362
|
+
remoteManagementWebSocketPrinter = new RemoteManagementWebSocketPrinter();
|
|
2363
|
+
}
|
|
2364
|
+
});
|
|
2365
|
+
|
|
1965
2366
|
// src/remote_management/websocket_handlers.ts
|
|
2367
|
+
function sendVersionResponse(ws) {
|
|
2368
|
+
const versionResponse = {
|
|
2369
|
+
cli_version: getVersion()
|
|
2370
|
+
};
|
|
2371
|
+
const payload = {
|
|
2372
|
+
command: "get-version",
|
|
2373
|
+
requestid: "0",
|
|
2374
|
+
response: JSON.stringify(versionResponse),
|
|
2375
|
+
error: false
|
|
2376
|
+
};
|
|
2377
|
+
ws.send(JSON.stringify(payload));
|
|
2378
|
+
}
|
|
1966
2379
|
function handleConnectionStatusMessage(firstMessage) {
|
|
1967
2380
|
try {
|
|
1968
2381
|
const text = typeof firstMessage === "string" ? firstMessage : firstMessage.toString();
|
|
@@ -1988,11 +2401,14 @@ var init_websocket_handlers = __esm({
|
|
|
1988
2401
|
init_types();
|
|
1989
2402
|
init_handler();
|
|
1990
2403
|
init_remote_schema();
|
|
2404
|
+
init_websocket_printer();
|
|
1991
2405
|
import_zod2 = __toESM(require("zod"), 1);
|
|
1992
2406
|
init_printer();
|
|
2407
|
+
init_util();
|
|
1993
2408
|
WebSocketCommandHandler = class {
|
|
1994
2409
|
constructor() {
|
|
1995
2410
|
this.tunnelHandler = new TunnelOperations();
|
|
2411
|
+
remoteManagementWebSocketPrinter.setTunnelHandler(this.tunnelHandler);
|
|
1996
2412
|
}
|
|
1997
2413
|
safeParse(text) {
|
|
1998
2414
|
if (!text) return void 0;
|
|
@@ -2017,35 +2433,157 @@ var init_websocket_handlers = __esm({
|
|
|
2017
2433
|
this.sendResponse(ws, resp);
|
|
2018
2434
|
}
|
|
2019
2435
|
async handleStartReq(req, raw) {
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2436
|
+
let queuedConfig;
|
|
2437
|
+
try {
|
|
2438
|
+
const dc = StartSchema.parse(raw);
|
|
2439
|
+
queuedConfig = dc.tunnelConfig;
|
|
2440
|
+
remoteManagementWebSocketPrinter.queueStart(dc.tunnelConfig);
|
|
2441
|
+
const result = await this.tunnelHandler.handleStart(dc.tunnelConfig);
|
|
2442
|
+
remoteManagementWebSocketPrinter.handleStartResult(dc.tunnelConfig, result);
|
|
2443
|
+
return this.wrapResponse(result, req);
|
|
2444
|
+
} catch (e) {
|
|
2445
|
+
if (queuedConfig) {
|
|
2446
|
+
remoteManagementWebSocketPrinter.failQueuedStart(queuedConfig, String(e));
|
|
2447
|
+
}
|
|
2448
|
+
if (e instanceof import_zod2.default.ZodError) {
|
|
2449
|
+
printer_default.warn("Validation failed for start request");
|
|
2450
|
+
return NewErrorResponseObject({ code: ErrorCode.InvalidBodyFormatError, message: "Validation failed" });
|
|
2451
|
+
}
|
|
2452
|
+
printer_default.warn(`Error in handleStartReq error: ${String(e)}`);
|
|
2453
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
async handleStartV2Req(req, raw) {
|
|
2457
|
+
let queuedConfig;
|
|
2458
|
+
try {
|
|
2459
|
+
const dc = StartV2Schema.parse(raw);
|
|
2460
|
+
queuedConfig = dc.tunnelConfig;
|
|
2461
|
+
remoteManagementWebSocketPrinter.queueStart(dc.tunnelConfig);
|
|
2462
|
+
const result = await this.tunnelHandler.handleStartV2(dc.tunnelConfig);
|
|
2463
|
+
remoteManagementWebSocketPrinter.handleStartResult(dc.tunnelConfig, result);
|
|
2464
|
+
return this.wrapResponse(result, req);
|
|
2465
|
+
} catch (e) {
|
|
2466
|
+
if (queuedConfig) {
|
|
2467
|
+
remoteManagementWebSocketPrinter.failQueuedStart(queuedConfig, String(e));
|
|
2468
|
+
}
|
|
2469
|
+
if (e instanceof import_zod2.default.ZodError) {
|
|
2470
|
+
printer_default.warn("Validation failed for start-v2 request");
|
|
2471
|
+
return NewErrorResponseObject({ code: ErrorCode.InvalidBodyFormatError, message: "Validation failed" });
|
|
2472
|
+
}
|
|
2473
|
+
printer_default.warn(`Error in handleStartV2Req error: ${String(e)}`);
|
|
2474
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2475
|
+
}
|
|
2024
2476
|
}
|
|
2025
2477
|
async handleStopReq(req, raw) {
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2478
|
+
try {
|
|
2479
|
+
const dc = StopSchema.parse(raw);
|
|
2480
|
+
remoteManagementWebSocketPrinter.printStopRequested(dc.tunnelID);
|
|
2481
|
+
const result = await this.tunnelHandler.handleStop(dc.tunnelID);
|
|
2482
|
+
remoteManagementWebSocketPrinter.handleStopResult(dc.tunnelID, result);
|
|
2483
|
+
return this.wrapResponse(result, req);
|
|
2484
|
+
} catch (e) {
|
|
2485
|
+
if (e instanceof import_zod2.default.ZodError) {
|
|
2486
|
+
printer_default.warn("Validation failed for stop request");
|
|
2487
|
+
return NewErrorResponseObject({ code: ErrorCode.InvalidBodyFormatError, message: "Validation failed" });
|
|
2488
|
+
}
|
|
2489
|
+
printer_default.warn(`Error in handleStopReq error: ${String(e)}`);
|
|
2490
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2491
|
+
}
|
|
2030
2492
|
}
|
|
2031
2493
|
async handleGetReq(req, raw) {
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2494
|
+
try {
|
|
2495
|
+
const dc = GetSchema.parse(raw);
|
|
2496
|
+
const result = await this.tunnelHandler.handleGet(dc.tunnelID);
|
|
2497
|
+
return this.wrapResponse(result, req);
|
|
2498
|
+
} catch (e) {
|
|
2499
|
+
if (e instanceof import_zod2.default.ZodError) {
|
|
2500
|
+
printer_default.warn("Validation failed for get request");
|
|
2501
|
+
return NewErrorResponseObject({ code: ErrorCode.InvalidBodyFormatError, message: "Validation failed" });
|
|
2502
|
+
}
|
|
2503
|
+
printer_default.warn(`Error in handleGetReq error: ${String(e)}`);
|
|
2504
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2505
|
+
}
|
|
2035
2506
|
}
|
|
2036
2507
|
async handleRestartReq(req, raw) {
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2508
|
+
try {
|
|
2509
|
+
const dc = RestartSchema.parse(raw);
|
|
2510
|
+
remoteManagementWebSocketPrinter.printRestartRequested(dc.tunnelID);
|
|
2511
|
+
const result = await this.tunnelHandler.handleRestart(dc.tunnelID);
|
|
2512
|
+
remoteManagementWebSocketPrinter.handleRestartResult(dc.tunnelID, result);
|
|
2513
|
+
return this.wrapResponse(result, req);
|
|
2514
|
+
} catch (e) {
|
|
2515
|
+
if (e instanceof import_zod2.default.ZodError) {
|
|
2516
|
+
printer_default.warn("Validation failed for restart request");
|
|
2517
|
+
return NewErrorResponseObject({ code: ErrorCode.InvalidBodyFormatError, message: "Validation failed" });
|
|
2518
|
+
}
|
|
2519
|
+
printer_default.warn(`Error in handleRestartReq error: ${String(e)}`);
|
|
2520
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2521
|
+
}
|
|
2040
2522
|
}
|
|
2041
2523
|
async handleUpdateConfigReq(req, raw) {
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2524
|
+
try {
|
|
2525
|
+
const dc = UpdateConfigSchema.parse(raw);
|
|
2526
|
+
const result = await this.tunnelHandler.handleUpdateConfig(dc.tunnelConfig);
|
|
2527
|
+
return this.wrapResponse(result, req);
|
|
2528
|
+
} catch (e) {
|
|
2529
|
+
if (e instanceof import_zod2.default.ZodError) {
|
|
2530
|
+
printer_default.warn("Validation failed for updateconfig request");
|
|
2531
|
+
return NewErrorResponseObject({ code: ErrorCode.InvalidBodyFormatError, message: "Validation failed" });
|
|
2532
|
+
}
|
|
2533
|
+
printer_default.warn(`Error in handleUpdateConfigReq error: ${String(e)}`);
|
|
2534
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
async handleUpdateConfigV2Req(req, raw) {
|
|
2538
|
+
try {
|
|
2539
|
+
const dc = UpdateConfigV2Schema.parse(raw);
|
|
2540
|
+
const result = await this.tunnelHandler.handleUpdateConfigV2(dc.tunnelConfig);
|
|
2541
|
+
return this.wrapResponse(result, req);
|
|
2542
|
+
} catch (e) {
|
|
2543
|
+
if (e instanceof import_zod2.default.ZodError) {
|
|
2544
|
+
printer_default.warn("Validation failed for update-config-v2 request");
|
|
2545
|
+
return NewErrorResponseObject({ code: ErrorCode.InvalidBodyFormatError, message: "Validation failed" });
|
|
2546
|
+
}
|
|
2547
|
+
printer_default.warn(`Error in handleUpdateConfigV2Req error: ${String(e)}`);
|
|
2548
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2549
|
+
}
|
|
2045
2550
|
}
|
|
2046
2551
|
async handleListReq(req) {
|
|
2047
|
-
|
|
2048
|
-
|
|
2552
|
+
try {
|
|
2553
|
+
const result = await this.tunnelHandler.handleList();
|
|
2554
|
+
remoteManagementWebSocketPrinter.monitorList(result);
|
|
2555
|
+
return this.wrapResponse(result, req);
|
|
2556
|
+
} catch (e) {
|
|
2557
|
+
printer_default.warn(`Error in handleListReq error: ${String(e)}`);
|
|
2558
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
async handleListV2Req(req) {
|
|
2562
|
+
try {
|
|
2563
|
+
const result = await this.tunnelHandler.handleListV2();
|
|
2564
|
+
remoteManagementWebSocketPrinter.monitorList(result);
|
|
2565
|
+
return this.wrapResponse(result, req);
|
|
2566
|
+
} catch (e) {
|
|
2567
|
+
printer_default.warn(`Error in handleListV2Req error: ${String(e)}`);
|
|
2568
|
+
return NewErrorResponseObject({ code: ErrorCode.InternalServerError, message: String(e) });
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
async handleGetVersionReq(ws, req) {
|
|
2572
|
+
try {
|
|
2573
|
+
const versionResponse = {
|
|
2574
|
+
cli_version: getVersion()
|
|
2575
|
+
};
|
|
2576
|
+
const payload = {
|
|
2577
|
+
command: req.command,
|
|
2578
|
+
requestid: req.requestid,
|
|
2579
|
+
response: JSON.stringify(versionResponse),
|
|
2580
|
+
error: false
|
|
2581
|
+
};
|
|
2582
|
+
ws.send(JSON.stringify(payload));
|
|
2583
|
+
} catch (e) {
|
|
2584
|
+
printer_default.warn(`Error in handleGetVersionReq error: ${String(e)}`);
|
|
2585
|
+
this.sendError(ws, req, String(e));
|
|
2586
|
+
}
|
|
2049
2587
|
}
|
|
2050
2588
|
wrapResponse(result, req) {
|
|
2051
2589
|
if (isErrorResponse(result)) {
|
|
@@ -2079,6 +2617,10 @@ var init_websocket_handlers = __esm({
|
|
|
2079
2617
|
response = await this.handleStartReq(req, raw);
|
|
2080
2618
|
break;
|
|
2081
2619
|
}
|
|
2620
|
+
case "start-v2": {
|
|
2621
|
+
response = await this.handleStartV2Req(req, raw);
|
|
2622
|
+
break;
|
|
2623
|
+
}
|
|
2082
2624
|
case "stop": {
|
|
2083
2625
|
response = await this.handleStopReq(req, raw);
|
|
2084
2626
|
break;
|
|
@@ -2095,10 +2637,22 @@ var init_websocket_handlers = __esm({
|
|
|
2095
2637
|
response = await this.handleUpdateConfigReq(req, raw);
|
|
2096
2638
|
break;
|
|
2097
2639
|
}
|
|
2640
|
+
case "update-config-v2": {
|
|
2641
|
+
response = await this.handleUpdateConfigV2Req(req, raw);
|
|
2642
|
+
break;
|
|
2643
|
+
}
|
|
2098
2644
|
case "list": {
|
|
2099
2645
|
response = await this.handleListReq(req);
|
|
2100
2646
|
break;
|
|
2101
2647
|
}
|
|
2648
|
+
case "list-v2": {
|
|
2649
|
+
response = await this.handleListV2Req(req);
|
|
2650
|
+
break;
|
|
2651
|
+
}
|
|
2652
|
+
case "get-version": {
|
|
2653
|
+
await this.handleGetVersionReq(ws, req);
|
|
2654
|
+
return;
|
|
2655
|
+
}
|
|
2102
2656
|
default:
|
|
2103
2657
|
if (typeof req.command === "string") {
|
|
2104
2658
|
logger.warn("Unknown command", { command: req.command });
|
|
@@ -2145,7 +2699,11 @@ async function parseRemoteManagement(values) {
|
|
|
2145
2699
|
if (typeof rmToken === "string" && rmToken.trim().length > 0) {
|
|
2146
2700
|
const manageHost = values["manage"];
|
|
2147
2701
|
try {
|
|
2148
|
-
|
|
2702
|
+
const remoteManagementConfig = {
|
|
2703
|
+
apiKey: rmToken,
|
|
2704
|
+
serverUrl: buildRemoteManagementWsUrl(manageHost)
|
|
2705
|
+
};
|
|
2706
|
+
await initiateRemoteManagement(remoteManagementConfig);
|
|
2149
2707
|
return { ok: true };
|
|
2150
2708
|
} catch (e) {
|
|
2151
2709
|
logger.error("Failed to initiate remote management:", e);
|
|
@@ -2153,11 +2711,11 @@ async function parseRemoteManagement(values) {
|
|
|
2153
2711
|
}
|
|
2154
2712
|
}
|
|
2155
2713
|
}
|
|
2156
|
-
async function initiateRemoteManagement(
|
|
2157
|
-
if (!
|
|
2714
|
+
async function initiateRemoteManagement(remoteManagementConfig) {
|
|
2715
|
+
if (!remoteManagementConfig.apiKey || remoteManagementConfig.apiKey.trim().length === 0) {
|
|
2158
2716
|
throw new Error("Remote management token is required (use --remote-management <TOKEN>)");
|
|
2159
2717
|
}
|
|
2160
|
-
const wsUrl =
|
|
2718
|
+
const wsUrl = remoteManagementConfig.serverUrl;
|
|
2161
2719
|
const wsHost = extractHostname(wsUrl);
|
|
2162
2720
|
logger.info("Remote management mode enabled.");
|
|
2163
2721
|
_stopRequested = false;
|
|
@@ -2173,7 +2731,7 @@ async function initiateRemoteManagement(token, manage) {
|
|
|
2173
2731
|
logConnecting();
|
|
2174
2732
|
setRemoteManagementState({ status: RemoteManagementStatus.Connecting, errorMessage: "" });
|
|
2175
2733
|
try {
|
|
2176
|
-
await handleWebSocketConnection(wsUrl, wsHost,
|
|
2734
|
+
await handleWebSocketConnection(wsUrl, wsHost, remoteManagementConfig.apiKey);
|
|
2177
2735
|
} catch (error) {
|
|
2178
2736
|
logger.warn("Remote management connection error", { error: String(error) });
|
|
2179
2737
|
}
|
|
@@ -2201,6 +2759,7 @@ async function handleWebSocketConnection(wsUrl, wsHost, token) {
|
|
|
2201
2759
|
};
|
|
2202
2760
|
ws.once("open", () => {
|
|
2203
2761
|
printer_default.success(`Connected to ${wsHost}`);
|
|
2762
|
+
setRemoteManagementState({ status: RemoteManagementStatus.Running, errorMessage: "" });
|
|
2204
2763
|
heartbeat = setInterval(() => {
|
|
2205
2764
|
if (ws.readyState === import_ws.default.OPEN) ws.ping();
|
|
2206
2765
|
}, PING_INTERVAL_MS);
|
|
@@ -2211,7 +2770,11 @@ async function handleWebSocketConnection(wsUrl, wsHost, token) {
|
|
|
2211
2770
|
if (firstMessage) {
|
|
2212
2771
|
firstMessage = false;
|
|
2213
2772
|
const ok = handleConnectionStatusMessage(data);
|
|
2214
|
-
if (!ok)
|
|
2773
|
+
if (!ok) {
|
|
2774
|
+
ws.close();
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
sendVersionResponse(ws);
|
|
2215
2778
|
return;
|
|
2216
2779
|
}
|
|
2217
2780
|
setRemoteManagementState({ status: RemoteManagementStatus.Running, errorMessage: "" });
|
|
@@ -2222,20 +2785,21 @@ async function handleWebSocketConnection(wsUrl, wsHost, token) {
|
|
|
2222
2785
|
}
|
|
2223
2786
|
});
|
|
2224
2787
|
ws.on("unexpected-response", (_, res) => {
|
|
2225
|
-
setRemoteManagementState({ status: RemoteManagementStatus.NotRunning, errorMessage: `HTTP ${res.statusCode}` });
|
|
2226
2788
|
if (res.statusCode === 401) {
|
|
2789
|
+
setRemoteManagementState({ status: RemoteManagementStatus.NotRunning, errorMessage: `HTTP ${res.statusCode}` });
|
|
2227
2790
|
printer_default.error("Unauthorized. Please enter a valid token.");
|
|
2228
2791
|
logger.error("Unauthorized (401) on remote management connect");
|
|
2792
|
+
ws.close();
|
|
2229
2793
|
} else {
|
|
2794
|
+
logger.warn("Unexpected HTTP response ", { statusCode: res.statusCode });
|
|
2230
2795
|
printer_default.warn(`Unexpected HTTP ${res.statusCode}. Retrying...`);
|
|
2231
|
-
|
|
2796
|
+
cleanup();
|
|
2232
2797
|
}
|
|
2233
|
-
ws.close();
|
|
2234
2798
|
});
|
|
2235
2799
|
ws.on("close", (code, reason) => {
|
|
2236
2800
|
setRemoteManagementState({ status: RemoteManagementStatus.NotRunning, errorMessage: "" });
|
|
2237
2801
|
logger.info("WebSocket closed", { code, reason: reason.toString() });
|
|
2238
|
-
printer_default.warn(`Disconnected (code: ${code}). Retrying...`);
|
|
2802
|
+
printer_default.warn(`Disconnected (code: ${code}). Retrying in ${RECONNECT_SLEEP_MS / 1e3}s...`);
|
|
2239
2803
|
cleanup();
|
|
2240
2804
|
});
|
|
2241
2805
|
ws.on("error", (err) => {
|
|
@@ -2325,6 +2889,7 @@ var init_options = __esm({
|
|
|
2325
2889
|
localport: { type: "string", short: "l", description: "Takes input as [protocol:][host:]port. Eg. --localport https://localhost:8000 OR -l 3000" },
|
|
2326
2890
|
debugger: { type: "string", short: "d", description: "Port for web debugger. Eg. --debugger 4300 OR -d 4300" },
|
|
2327
2891
|
token: { type: "string", description: "Token for authentication. Eg. --token TOKEN_VALUE" },
|
|
2892
|
+
force: { type: "boolean", short: "f", description: "Forcefully close existing tunnels and establish a new tunnel" },
|
|
2328
2893
|
// Logging options (CLI overrides env)
|
|
2329
2894
|
loglevel: { type: "string", description: "Logging level: ERROR, INFO, DEBUG. Overrides PINGGY_LOG_LEVEL environment variable" },
|
|
2330
2895
|
logfile: { type: "string", description: "Path to log file. Overrides PINGGY_LOG_FILE environment variable" },
|
|
@@ -2340,7 +2905,8 @@ var init_options = __esm({
|
|
|
2340
2905
|
// Remote Control
|
|
2341
2906
|
"remote-management": { type: "string", description: "Enable remote management of tunnels with token. Eg. --remote-management API_KEY" },
|
|
2342
2907
|
manage: { type: "string", description: "Provide a server address to manage tunnels. Eg --manage dashboard.pinggy.io" },
|
|
2343
|
-
|
|
2908
|
+
noTui: { type: "boolean", description: "Disable TUI in remote management mode" },
|
|
2909
|
+
notui: { type: "boolean", description: "hidden", hidden: true },
|
|
2344
2910
|
// Misc
|
|
2345
2911
|
version: { type: "boolean", description: "Print version" },
|
|
2346
2912
|
// Help
|
|
@@ -2421,8 +2987,8 @@ var init_defaults = __esm({
|
|
|
2421
2987
|
});
|
|
2422
2988
|
|
|
2423
2989
|
// src/cli/extendedOptions.ts
|
|
2424
|
-
function parseExtendedOptions(options, config) {
|
|
2425
|
-
if (!options) return;
|
|
2990
|
+
function parseExtendedOptions(options, config, localServerTls) {
|
|
2991
|
+
if (!options) return localServerTls;
|
|
2426
2992
|
for (const opt of options) {
|
|
2427
2993
|
const [key, value] = opt.replace(/^"|"$/g, "").split(/:(.+)/).filter(Boolean);
|
|
2428
2994
|
switch (key) {
|
|
@@ -2446,10 +3012,16 @@ function parseExtendedOptions(options, config) {
|
|
|
2446
3012
|
case "fullrequesturl":
|
|
2447
3013
|
config.originalRequestUrl = true;
|
|
2448
3014
|
break;
|
|
2449
|
-
default:
|
|
2450
|
-
|
|
2451
|
-
|
|
3015
|
+
default: {
|
|
3016
|
+
if (value && (value.startsWith("localServerTls") || value.startsWith("localservertls"))) {
|
|
3017
|
+
const parts = value.split(/:(.+)/);
|
|
3018
|
+
localServerTls = parts[1] ? parts[1] : "";
|
|
3019
|
+
} else {
|
|
3020
|
+
printer_default.warn(`Unknown extended option "${value}"`);
|
|
3021
|
+
logger.warn(`Warning: Unknown extended option "${value}"`);
|
|
3022
|
+
}
|
|
2452
3023
|
break;
|
|
3024
|
+
}
|
|
2453
3025
|
}
|
|
2454
3026
|
break;
|
|
2455
3027
|
case "w":
|
|
@@ -2520,6 +3092,7 @@ function parseExtendedOptions(options, config) {
|
|
|
2520
3092
|
break;
|
|
2521
3093
|
}
|
|
2522
3094
|
}
|
|
3095
|
+
return localServerTls;
|
|
2523
3096
|
}
|
|
2524
3097
|
function isValidIpV4Cidr(input) {
|
|
2525
3098
|
if (input.includes("/")) {
|
|
@@ -2570,7 +3143,7 @@ function parseUserAndDomain(str) {
|
|
|
2570
3143
|
const [user, domain] = str.split("@", 2);
|
|
2571
3144
|
if (domainRegex.test(domain)) {
|
|
2572
3145
|
let processKeyword2 = function(keyword) {
|
|
2573
|
-
if ([
|
|
3146
|
+
if ([import_pinggy4.TunnelType.Http, import_pinggy4.TunnelType.Tcp, import_pinggy4.TunnelType.Tls, import_pinggy4.TunnelType.Udp, import_pinggy4.TunnelType.TlsTcp].includes(keyword)) {
|
|
2574
3147
|
type = keyword;
|
|
2575
3148
|
} else if (keyword === "force") {
|
|
2576
3149
|
forceFlag = true;
|
|
@@ -2639,9 +3212,9 @@ function parseUsers(positionalArgs, explicitToken) {
|
|
|
2639
3212
|
return { token, server, type, forceFlag, qrCode, remaining };
|
|
2640
3213
|
}
|
|
2641
3214
|
function parseType(finalConfig, values, inferredType) {
|
|
2642
|
-
const t = inferredType || values.type
|
|
2643
|
-
if (t ===
|
|
2644
|
-
|
|
3215
|
+
const t = inferredType || values.type;
|
|
3216
|
+
if (t === import_pinggy4.TunnelType.Http || t === import_pinggy4.TunnelType.Tcp || t === import_pinggy4.TunnelType.Tls || t === import_pinggy4.TunnelType.Udp || t === import_pinggy4.TunnelType.TlsTcp) {
|
|
3217
|
+
return t;
|
|
2645
3218
|
}
|
|
2646
3219
|
}
|
|
2647
3220
|
function parseLocalPort(finalConfig, values) {
|
|
@@ -2775,15 +3348,14 @@ function parseAdditionalForwarding(forwarding) {
|
|
|
2775
3348
|
return new Error("forwarding address incorrect: invalid local port");
|
|
2776
3349
|
}
|
|
2777
3350
|
return {
|
|
2778
|
-
protocol,
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
localDomain,
|
|
2782
|
-
localPort
|
|
3351
|
+
type: protocol,
|
|
3352
|
+
listenAddress: `${remoteDomainRaw}:${remotePort}`,
|
|
3353
|
+
address: `${localDomain}:${localPort}`
|
|
2783
3354
|
};
|
|
2784
3355
|
}
|
|
2785
|
-
function parseReverseTunnelAddr(finalConfig, values) {
|
|
3356
|
+
function parseReverseTunnelAddr(finalConfig, values, primaryType) {
|
|
2786
3357
|
const reverseTunnel = values.R;
|
|
3358
|
+
let forwardingData = [];
|
|
2787
3359
|
if ((!Array.isArray(reverseTunnel) || reverseTunnel.length === 0) && !values.localport && !finalConfig.forwarding) {
|
|
2788
3360
|
return new Error("local port not specified. Please use '-h' option for help.");
|
|
2789
3361
|
}
|
|
@@ -2795,18 +3367,21 @@ function parseReverseTunnelAddr(finalConfig, values) {
|
|
|
2795
3367
|
if (slicedForwarding.length === 3) {
|
|
2796
3368
|
const parsed = parseDefaultForwarding(forwarding);
|
|
2797
3369
|
if (parsed instanceof Error) return parsed;
|
|
2798
|
-
|
|
3370
|
+
forwardingData.push({
|
|
3371
|
+
address: `${parsed.localDomain}:${parsed.localPort}`,
|
|
3372
|
+
type: primaryType || import_pinggy4.TunnelType.Http
|
|
3373
|
+
});
|
|
2799
3374
|
} else if (slicedForwarding.length === 4) {
|
|
2800
|
-
finalConfig.additionalForwarding ?? (finalConfig.additionalForwarding = []);
|
|
2801
3375
|
const parsed = parseAdditionalForwarding(forwarding);
|
|
2802
3376
|
if (parsed instanceof Error) return parsed;
|
|
2803
|
-
|
|
3377
|
+
forwardingData.push(parsed);
|
|
2804
3378
|
} else {
|
|
2805
3379
|
return new Error(
|
|
2806
3380
|
"Incorrect command line arguments: reverse tunnel address incorrect. Please use '-h' option for help."
|
|
2807
3381
|
);
|
|
2808
3382
|
}
|
|
2809
3383
|
}
|
|
3384
|
+
finalConfig.forwarding = forwardingData;
|
|
2810
3385
|
return null;
|
|
2811
3386
|
}
|
|
2812
3387
|
function parseLocalTunnelAddr(finalConfig, values) {
|
|
@@ -2842,13 +3417,19 @@ function parseToken(finalConfig, explicitToken) {
|
|
|
2842
3417
|
}
|
|
2843
3418
|
}
|
|
2844
3419
|
function parseArgs(finalConfig, remainingPositionals) {
|
|
2845
|
-
|
|
3420
|
+
let localserverTls = "";
|
|
3421
|
+
localserverTls = parseExtendedOptions(remainingPositionals, finalConfig, localserverTls);
|
|
3422
|
+
if (localserverTls.length > 0 && finalConfig.forwarding) {
|
|
3423
|
+
if (typeof finalConfig.forwarding[0] === "object" && "address" in finalConfig.forwarding[0]) {
|
|
3424
|
+
finalConfig.forwarding[0].address = `https://${finalConfig.forwarding[0].address}`;
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
2846
3427
|
}
|
|
2847
3428
|
function storeJson(config, saveconf) {
|
|
2848
3429
|
if (saveconf) {
|
|
2849
3430
|
const path5 = saveconf;
|
|
2850
3431
|
try {
|
|
2851
|
-
|
|
3432
|
+
import_fs4.default.writeFileSync(path5, JSON.stringify(config, null, 2), { encoding: "utf-8", flag: "w" });
|
|
2852
3433
|
logger.info(`Configuration saved to ${path5}`);
|
|
2853
3434
|
} catch (err) {
|
|
2854
3435
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -2859,9 +3440,9 @@ function storeJson(config, saveconf) {
|
|
|
2859
3440
|
function loadJsonConfig(config) {
|
|
2860
3441
|
const configpath = config["conf"];
|
|
2861
3442
|
if (typeof configpath === "string" && configpath.trim().length > 0) {
|
|
2862
|
-
const filepath =
|
|
3443
|
+
const filepath = import_path4.default.resolve(configpath);
|
|
2863
3444
|
try {
|
|
2864
|
-
const data =
|
|
3445
|
+
const data = import_fs4.default.readFileSync(filepath, { encoding: "utf-8" });
|
|
2865
3446
|
const json = JSON.parse(data);
|
|
2866
3447
|
return json;
|
|
2867
3448
|
} catch (err) {
|
|
@@ -2880,7 +3461,7 @@ function isSaveConfOption(values) {
|
|
|
2880
3461
|
function parseServe(finalConfig, values) {
|
|
2881
3462
|
const sv = values.serve;
|
|
2882
3463
|
if (typeof sv !== "string" || sv.trim().length === 0) return null;
|
|
2883
|
-
finalConfig.serve = sv;
|
|
3464
|
+
finalConfig.optional.serve = sv;
|
|
2884
3465
|
return null;
|
|
2885
3466
|
}
|
|
2886
3467
|
function parseAutoReconnect(finalConfig, values) {
|
|
@@ -2918,21 +3499,23 @@ async function buildFinalConfig(values, positionals) {
|
|
|
2918
3499
|
...defaultOptions,
|
|
2919
3500
|
...configFromFile || {},
|
|
2920
3501
|
// Apply loaded config on top of defaults
|
|
2921
|
-
|
|
3502
|
+
configId: getRandomId(),
|
|
2922
3503
|
token: token || (configFromFile?.token || (typeof values.token === "string" ? values.token : "")),
|
|
2923
3504
|
serverAddress: server || (configFromFile?.serverAddress || defaultOptions.serverAddress),
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
3505
|
+
isQRCode: qrCode || (configFromFile?.isQRCode || false),
|
|
3506
|
+
autoReconnect: configFromFile?.autoReconnect ? configFromFile.autoReconnect : defaultOptions.autoReconnect,
|
|
3507
|
+
optional: {
|
|
3508
|
+
serve: configFromFile?.optional?.serve || void 0,
|
|
3509
|
+
noTui: values.noTui || values.notui || (configFromFile?.optional?.noTui || false)
|
|
3510
|
+
}
|
|
2928
3511
|
};
|
|
2929
|
-
parseType(finalConfig, values, type);
|
|
3512
|
+
type = parseType(finalConfig, values, type);
|
|
2930
3513
|
parseToken(finalConfig, token || values.token);
|
|
2931
3514
|
const dbgErr = parseDebugger(finalConfig, values);
|
|
2932
3515
|
if (dbgErr instanceof Error) throw dbgErr;
|
|
2933
3516
|
const lpErr = parseLocalPort(finalConfig, values);
|
|
2934
3517
|
if (lpErr instanceof Error) throw lpErr;
|
|
2935
|
-
const rErr = parseReverseTunnelAddr(finalConfig, values);
|
|
3518
|
+
const rErr = parseReverseTunnelAddr(finalConfig, values, type);
|
|
2936
3519
|
if (rErr instanceof Error) throw rErr;
|
|
2937
3520
|
const lErr = parseLocalTunnelAddr(finalConfig, values);
|
|
2938
3521
|
if (lErr instanceof Error) throw lErr;
|
|
@@ -2940,12 +3523,12 @@ async function buildFinalConfig(values, positionals) {
|
|
|
2940
3523
|
if (serveErr instanceof Error) throw serveErr;
|
|
2941
3524
|
const autoReconnectErr = parseAutoReconnect(finalConfig, values);
|
|
2942
3525
|
if (autoReconnectErr instanceof Error) throw autoReconnectErr;
|
|
2943
|
-
if (forceFlag) finalConfig.force = true;
|
|
3526
|
+
if (forceFlag || values.force) finalConfig.force = true;
|
|
2944
3527
|
parseArgs(finalConfig, remainingPositionals);
|
|
2945
3528
|
storeJson(finalConfig, saveconf);
|
|
2946
3529
|
return finalConfig;
|
|
2947
3530
|
}
|
|
2948
|
-
var
|
|
3531
|
+
var import_pinggy4, import_fs4, import_path4, domainRegex, KEYWORDS, VALID_PROTOCOLS;
|
|
2949
3532
|
var init_buildConfig = __esm({
|
|
2950
3533
|
"src/cli/buildConfig.ts"() {
|
|
2951
3534
|
"use strict";
|
|
@@ -2954,16 +3537,16 @@ var init_buildConfig = __esm({
|
|
|
2954
3537
|
init_extendedOptions();
|
|
2955
3538
|
init_logger();
|
|
2956
3539
|
init_util();
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
3540
|
+
import_pinggy4 = require("@pinggy/pinggy");
|
|
3541
|
+
import_fs4 = __toESM(require("fs"), 1);
|
|
3542
|
+
import_path4 = __toESM(require("path"), 1);
|
|
2960
3543
|
domainRegex = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
|
|
2961
3544
|
KEYWORDS = /* @__PURE__ */ new Set([
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
3545
|
+
import_pinggy4.TunnelType.Http,
|
|
3546
|
+
import_pinggy4.TunnelType.Tcp,
|
|
3547
|
+
import_pinggy4.TunnelType.Tls,
|
|
3548
|
+
import_pinggy4.TunnelType.Udp,
|
|
3549
|
+
import_pinggy4.TunnelType.TlsTcp,
|
|
2967
3550
|
"force",
|
|
2968
3551
|
"qr"
|
|
2969
3552
|
]);
|
|
@@ -3000,7 +3583,7 @@ function preprocessWindowsArgs(args) {
|
|
|
3000
3583
|
function parseCliArgs(options) {
|
|
3001
3584
|
const rawArgs = process.argv.slice(2);
|
|
3002
3585
|
const processedArgs = preprocessWindowsArgs(rawArgs);
|
|
3003
|
-
const parsed = (0,
|
|
3586
|
+
const parsed = (0, import_util6.parseArgs)({
|
|
3004
3587
|
args: processedArgs,
|
|
3005
3588
|
options,
|
|
3006
3589
|
allowPositionals: true
|
|
@@ -3011,12 +3594,12 @@ function parseCliArgs(options) {
|
|
|
3011
3594
|
hasAnyArgs
|
|
3012
3595
|
};
|
|
3013
3596
|
}
|
|
3014
|
-
var
|
|
3597
|
+
var import_util6, os2;
|
|
3015
3598
|
var init_parseArgs = __esm({
|
|
3016
3599
|
"src/utils/parseArgs.ts"() {
|
|
3017
3600
|
"use strict";
|
|
3018
3601
|
init_cjs_shims();
|
|
3019
|
-
|
|
3602
|
+
import_util6 = require("util");
|
|
3020
3603
|
os2 = __toESM(require("os"), 1);
|
|
3021
3604
|
}
|
|
3022
3605
|
});
|
|
@@ -4448,7 +5031,7 @@ async function launchTui(finalConfig, urls, greet, tunnel) {
|
|
|
4448
5031
|
}
|
|
4449
5032
|
}
|
|
4450
5033
|
async function startCli(finalConfig, manager) {
|
|
4451
|
-
if (!finalConfig.
|
|
5034
|
+
if (!finalConfig.optional?.noTui && finalConfig.webDebugger === "") {
|
|
4452
5035
|
const freePort = await getFreePort(finalConfig.webDebugger || "");
|
|
4453
5036
|
finalConfig.webDebugger = `localhost:${freePort}`;
|
|
4454
5037
|
}
|
|
@@ -4456,7 +5039,7 @@ async function startCli(finalConfig, manager) {
|
|
|
4456
5039
|
const manager2 = TunnelManager.getInstance();
|
|
4457
5040
|
const tunnel = await manager2.createTunnel(finalConfig);
|
|
4458
5041
|
printer_default.startSpinner("Connecting to Pinggy...");
|
|
4459
|
-
if (!finalConfig.
|
|
5042
|
+
if (!finalConfig.optional?.noTui) {
|
|
4460
5043
|
manager2.registerStatsListener(tunnel.tunnelid, (tunnelId, stats) => {
|
|
4461
5044
|
globalThis.__PINGGY_TUNNEL_STATS__?.(stats);
|
|
4462
5045
|
});
|
|
@@ -4466,26 +5049,26 @@ async function startCli(finalConfig, manager) {
|
|
|
4466
5049
|
});
|
|
4467
5050
|
await manager2.startTunnel(tunnel.tunnelid);
|
|
4468
5051
|
printer_default.stopSpinnerSuccess(" Connected to Pinggy");
|
|
4469
|
-
printer_default.success(
|
|
4470
|
-
printer_default.print(
|
|
5052
|
+
printer_default.success(import_picocolors4.default.bold("Tunnel established!"));
|
|
5053
|
+
printer_default.print(import_picocolors4.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4471
5054
|
TunnelData.urls = await manager2.getTunnelUrls(tunnel.tunnelid);
|
|
4472
5055
|
TunnelData.greet = await manager2.getTunnelGreetMessage(tunnel.tunnelid);
|
|
4473
|
-
printer_default.info(
|
|
5056
|
+
printer_default.info(import_picocolors4.default.cyanBright("Remote URLs:"));
|
|
4474
5057
|
(TunnelData.urls ?? []).forEach(
|
|
4475
|
-
(url) => printer_default.print(" " +
|
|
5058
|
+
(url) => printer_default.print(" " + import_picocolors4.default.magentaBright(url))
|
|
4476
5059
|
);
|
|
4477
|
-
printer_default.print(
|
|
5060
|
+
printer_default.print(import_picocolors4.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4478
5061
|
if (TunnelData.greet?.includes("not authenticated")) {
|
|
4479
|
-
printer_default.warn(
|
|
5062
|
+
printer_default.warn(import_picocolors4.default.yellowBright(TunnelData.greet));
|
|
4480
5063
|
} else if (TunnelData.greet?.includes("authenticated as")) {
|
|
4481
5064
|
const emailMatch = /authenticated as (.+)/.exec(TunnelData.greet);
|
|
4482
5065
|
if (emailMatch) {
|
|
4483
5066
|
const email = emailMatch[1];
|
|
4484
|
-
printer_default.info(
|
|
5067
|
+
printer_default.info(import_picocolors4.default.cyanBright("Authenticated as: " + email));
|
|
4485
5068
|
}
|
|
4486
5069
|
}
|
|
4487
|
-
printer_default.print(
|
|
4488
|
-
printer_default.print(
|
|
5070
|
+
printer_default.print(import_picocolors4.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5071
|
+
printer_default.print(import_picocolors4.default.gray("\nPress Ctrl+C to stop the tunnel.\n"));
|
|
4489
5072
|
manager2.registerWillReconnectListener(tunnel.tunnelid, (tunnelId, error, messages) => {
|
|
4490
5073
|
if (activeTui) {
|
|
4491
5074
|
const msg = messages?.join("\n") || error || "Tunnel disconnected, reconnecting...";
|
|
@@ -4555,34 +5138,34 @@ async function startCli(finalConfig, manager) {
|
|
|
4555
5138
|
printer_default.stopSpinnerSuccess("Reconnected to Pinggy");
|
|
4556
5139
|
} catch (e) {
|
|
4557
5140
|
}
|
|
4558
|
-
printer_default.success(
|
|
4559
|
-
printer_default.print(
|
|
5141
|
+
printer_default.success(import_picocolors4.default.bold("Tunnel re-established!"));
|
|
5142
|
+
printer_default.print(import_picocolors4.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4560
5143
|
TunnelData.urls = urls;
|
|
4561
5144
|
TunnelData.greet = await manager2.getTunnelGreetMessage(tunnel.tunnelid);
|
|
4562
|
-
printer_default.info(
|
|
5145
|
+
printer_default.info(import_picocolors4.default.cyanBright("Remote URLs:"));
|
|
4563
5146
|
(TunnelData.urls ?? []).forEach(
|
|
4564
|
-
(url) => printer_default.print(" " +
|
|
5147
|
+
(url) => printer_default.print(" " + import_picocolors4.default.magentaBright(url))
|
|
4565
5148
|
);
|
|
4566
|
-
printer_default.print(
|
|
5149
|
+
printer_default.print(import_picocolors4.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4567
5150
|
if (TunnelData.greet?.includes("not authenticated")) {
|
|
4568
|
-
printer_default.warn(
|
|
5151
|
+
printer_default.warn(import_picocolors4.default.yellowBright(TunnelData.greet));
|
|
4569
5152
|
} else if (TunnelData.greet?.includes("authenticated as")) {
|
|
4570
5153
|
const emailMatch = /authenticated as (.+)/.exec(TunnelData.greet);
|
|
4571
5154
|
if (emailMatch) {
|
|
4572
5155
|
const email = emailMatch[1];
|
|
4573
|
-
printer_default.info(
|
|
5156
|
+
printer_default.info(import_picocolors4.default.cyanBright("Authenticated as: " + email));
|
|
4574
5157
|
}
|
|
4575
5158
|
}
|
|
4576
|
-
printer_default.print(
|
|
4577
|
-
printer_default.print(
|
|
4578
|
-
if (!finalConfig.
|
|
5159
|
+
printer_default.print(import_picocolors4.default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5160
|
+
printer_default.print(import_picocolors4.default.gray("\nPress Ctrl+C to stop the tunnel.\n"));
|
|
5161
|
+
if (!finalConfig.optional?.noTui) {
|
|
4579
5162
|
await launchTui(finalConfig, TunnelData.urls, TunnelData.greet, tunnel);
|
|
4580
5163
|
}
|
|
4581
5164
|
});
|
|
4582
5165
|
} catch (e) {
|
|
4583
5166
|
logger.debug("Failed to register start listener", e);
|
|
4584
5167
|
}
|
|
4585
|
-
if (!finalConfig.
|
|
5168
|
+
if (!finalConfig.optional?.noTui) {
|
|
4586
5169
|
await launchTui(finalConfig, TunnelData.urls, TunnelData.greet, tunnel);
|
|
4587
5170
|
}
|
|
4588
5171
|
} catch (err) {
|
|
@@ -4591,7 +5174,7 @@ async function startCli(finalConfig, manager) {
|
|
|
4591
5174
|
throw err;
|
|
4592
5175
|
}
|
|
4593
5176
|
}
|
|
4594
|
-
var
|
|
5177
|
+
var import_picocolors4, TunnelData, activeTui, disconnectState;
|
|
4595
5178
|
var init_starCli = __esm({
|
|
4596
5179
|
"src/cli/starCli.ts"() {
|
|
4597
5180
|
"use strict";
|
|
@@ -4600,7 +5183,7 @@ var init_starCli = __esm({
|
|
|
4600
5183
|
init_TunnelManager();
|
|
4601
5184
|
init_getFreePort();
|
|
4602
5185
|
init_logger();
|
|
4603
|
-
|
|
5186
|
+
import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
4604
5187
|
init_blessed();
|
|
4605
5188
|
TunnelData = {
|
|
4606
5189
|
urls: null,
|
|
@@ -4657,7 +5240,7 @@ async function main() {
|
|
|
4657
5240
|
printer_default.error(error);
|
|
4658
5241
|
}
|
|
4659
5242
|
}
|
|
4660
|
-
var
|
|
5243
|
+
var import_url2, import_process, import_fs5, currentFile, entryFile;
|
|
4661
5244
|
var init_main = __esm({
|
|
4662
5245
|
"src/main.ts"() {
|
|
4663
5246
|
"use strict";
|
|
@@ -4673,15 +5256,15 @@ var init_main = __esm({
|
|
|
4673
5256
|
init_starCli();
|
|
4674
5257
|
init_util();
|
|
4675
5258
|
init_handler();
|
|
4676
|
-
|
|
5259
|
+
import_url2 = require("url");
|
|
4677
5260
|
import_process = require("process");
|
|
4678
|
-
|
|
5261
|
+
import_fs5 = require("fs");
|
|
4679
5262
|
init_logger();
|
|
4680
5263
|
init_remoteManagement();
|
|
4681
|
-
currentFile = (0,
|
|
5264
|
+
currentFile = (0, import_url2.fileURLToPath)(importMetaUrl);
|
|
4682
5265
|
entryFile = null;
|
|
4683
5266
|
try {
|
|
4684
|
-
entryFile = import_process.argv[1] ? (0,
|
|
5267
|
+
entryFile = import_process.argv[1] ? (0, import_fs5.realpathSync)(import_process.argv[1]) : null;
|
|
4685
5268
|
} catch (e) {
|
|
4686
5269
|
entryFile = null;
|
|
4687
5270
|
}
|