pinggy 0.4.6 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -4
- package/dist/{chunk-STEISST3.js → chunk-443UO6IY.js} +1 -0
- package/dist/index.cjs +703 -94
- package/dist/index.js +2 -2
- package/dist/{main-XKFFUSKJ.js → main-PUM4SD6B.js} +659 -86
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3085,9 +3085,13 @@ var init_options = __esm({
|
|
|
3085
3085
|
vv: { type: "boolean", description: "Enable detailed logging for the Node.js SDK and Libpinggy, including both info and debug level logs." },
|
|
3086
3086
|
vvv: { type: "boolean", description: "Enable all logs from Cli, SDK and internal components." },
|
|
3087
3087
|
autoreconnect: { type: "string", short: "a", description: "Automatically reconnect tunnel on failure (enabled by default). Use -a false to disable." },
|
|
3088
|
-
// Save and load config
|
|
3088
|
+
// Save and load config (legacy file-based)
|
|
3089
3089
|
saveconf: { type: "string", description: "Create the configuration file based on the options provided here" },
|
|
3090
3090
|
conf: { type: "string", description: "Use the configuration file as base. Other options will be used to override this file" },
|
|
3091
|
+
// Used by `pinggy config save` and `buildAndStartTunnel` save flow
|
|
3092
|
+
save: { type: "boolean", short: "s", description: "Save the tunnel config (use with config save or -l)", hidden: true },
|
|
3093
|
+
name: { type: "string", description: "Name for the tunnel config", hidden: true },
|
|
3094
|
+
auto: { type: "boolean", description: "Mark tunnel config for auto-start", hidden: true },
|
|
3091
3095
|
// File server
|
|
3092
3096
|
serve: { type: "string", description: "Start a webserver to serve files from the specified path. Eg --serve /path/to/files" },
|
|
3093
3097
|
// Remote Control
|
|
@@ -3137,7 +3141,21 @@ function printHelpMessage() {
|
|
|
3137
3141
|
console.log(" pinggy -R0:localhost:3000 # Basic HTTP tunnel");
|
|
3138
3142
|
console.log(" pinggy --type tcp -R0:localhost:22 # TCP tunnel for SSH");
|
|
3139
3143
|
console.log(" pinggy -R0:localhost:8080 -L4300:localhost:4300 # HTTP tunnel with debugger");
|
|
3140
|
-
console.log(" pinggy tcp@ap.example.com -R0:localhost:22 # TCP tunnel to region
|
|
3144
|
+
console.log(" pinggy tcp@ap.example.com -R0:localhost:22 # TCP tunnel to region");
|
|
3145
|
+
console.log("\nConfig Management:");
|
|
3146
|
+
console.log(" pinggy config list # List saved configs");
|
|
3147
|
+
console.log(" pinggy config show my-tunnel # Show config details");
|
|
3148
|
+
console.log(" pinggy config save my-tunnel -l 3000 token@pro.pinggy.io # Save config");
|
|
3149
|
+
console.log(" pinggy config save my-tunnel --auto -l 3000 # Save with auto-start");
|
|
3150
|
+
console.log(" pinggy config update my-tunnel -l 4000 # Update saved config");
|
|
3151
|
+
console.log(" pinggy config delete my-tunnel # Delete saved config");
|
|
3152
|
+
console.log(" pinggy config auto my-tunnel # Enable auto-start");
|
|
3153
|
+
console.log(" pinggy config noauto my-tunnel # Disable auto-start");
|
|
3154
|
+
console.log("\nStart Saved Tunnels:");
|
|
3155
|
+
console.log(" pinggy start my-tunnel # Start saved tunnel");
|
|
3156
|
+
console.log(" pinggy start my-tunnel -l 4000 # Start with runtime overrides");
|
|
3157
|
+
console.log(" pinggy start tunnela tunnelb # Start multiple tunnels");
|
|
3158
|
+
console.log(" pinggy start --all # Start all auto-start tunnels\n");
|
|
3141
3159
|
}
|
|
3142
3160
|
var init_help = __esm({
|
|
3143
3161
|
"src/cli/help.ts"() {
|
|
@@ -3147,6 +3165,74 @@ var init_help = __esm({
|
|
|
3147
3165
|
}
|
|
3148
3166
|
});
|
|
3149
3167
|
|
|
3168
|
+
// src/utils/parseArgs.ts
|
|
3169
|
+
function isAttachedReverseOrLocalFlag(arg) {
|
|
3170
|
+
return /^-[RL].+/.test(arg);
|
|
3171
|
+
}
|
|
3172
|
+
function shouldMergeReverseOrLocalFragment(current, next) {
|
|
3173
|
+
if (next.startsWith("-")) {
|
|
3174
|
+
return false;
|
|
3175
|
+
}
|
|
3176
|
+
if (next.startsWith(".")) {
|
|
3177
|
+
return true;
|
|
3178
|
+
}
|
|
3179
|
+
const body = current.slice(2);
|
|
3180
|
+
if (body.endsWith(":")) {
|
|
3181
|
+
return true;
|
|
3182
|
+
}
|
|
3183
|
+
if (body.includes("//") && !body.includes(":")) {
|
|
3184
|
+
return true;
|
|
3185
|
+
}
|
|
3186
|
+
return false;
|
|
3187
|
+
}
|
|
3188
|
+
function preprocessWindowsArgs(args) {
|
|
3189
|
+
if (os2.platform() !== "win32") {
|
|
3190
|
+
return args;
|
|
3191
|
+
}
|
|
3192
|
+
;
|
|
3193
|
+
const out = [];
|
|
3194
|
+
let i = 0;
|
|
3195
|
+
while (i < args.length) {
|
|
3196
|
+
const arg = args[i];
|
|
3197
|
+
if (isAttachedReverseOrLocalFlag(arg)) {
|
|
3198
|
+
let merged = arg;
|
|
3199
|
+
while (i + 1 < args.length && shouldMergeReverseOrLocalFragment(merged, args[i + 1])) {
|
|
3200
|
+
merged += args[i + 1];
|
|
3201
|
+
i++;
|
|
3202
|
+
}
|
|
3203
|
+
out.push(merged);
|
|
3204
|
+
i++;
|
|
3205
|
+
continue;
|
|
3206
|
+
}
|
|
3207
|
+
out.push(arg);
|
|
3208
|
+
i++;
|
|
3209
|
+
}
|
|
3210
|
+
return out;
|
|
3211
|
+
}
|
|
3212
|
+
function parseCliArgs(options, overrideArgs) {
|
|
3213
|
+
const rawArgs = overrideArgs ?? process.argv.slice(2);
|
|
3214
|
+
const processedArgs = preprocessWindowsArgs(rawArgs);
|
|
3215
|
+
const parsed = (0, import_util5.parseArgs)({
|
|
3216
|
+
args: processedArgs,
|
|
3217
|
+
options,
|
|
3218
|
+
allowPositionals: true
|
|
3219
|
+
});
|
|
3220
|
+
const hasAnyArgs = parsed.positionals.length > 0 || Object.values(parsed.values).some((v) => v !== void 0 && v !== false);
|
|
3221
|
+
return {
|
|
3222
|
+
...parsed,
|
|
3223
|
+
hasAnyArgs
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
var import_util5, os2;
|
|
3227
|
+
var init_parseArgs = __esm({
|
|
3228
|
+
"src/utils/parseArgs.ts"() {
|
|
3229
|
+
"use strict";
|
|
3230
|
+
init_cjs_shims();
|
|
3231
|
+
import_util5 = require("util");
|
|
3232
|
+
os2 = __toESM(require("os"), 1);
|
|
3233
|
+
}
|
|
3234
|
+
});
|
|
3235
|
+
|
|
3150
3236
|
// src/cli/defaults.ts
|
|
3151
3237
|
var defaultOptions;
|
|
3152
3238
|
var init_defaults = __esm({
|
|
@@ -3154,6 +3240,7 @@ var init_defaults = __esm({
|
|
|
3154
3240
|
"use strict";
|
|
3155
3241
|
init_cjs_shims();
|
|
3156
3242
|
defaultOptions = {
|
|
3243
|
+
version: "1.0",
|
|
3157
3244
|
token: void 0,
|
|
3158
3245
|
// No default token
|
|
3159
3246
|
serverAddress: "a.pinggy.io",
|
|
@@ -3656,7 +3743,7 @@ function parseToken(finalConfig, explicitToken) {
|
|
|
3656
3743
|
finalConfig.token = explicitToken;
|
|
3657
3744
|
}
|
|
3658
3745
|
}
|
|
3659
|
-
function
|
|
3746
|
+
function parseArgs2(finalConfig, remainingPositionals) {
|
|
3660
3747
|
let localserverTls = "";
|
|
3661
3748
|
localserverTls = parseExtendedOptions(remainingPositionals, finalConfig, localserverTls);
|
|
3662
3749
|
if (localserverTls.length > 0 && finalConfig.forwarding) {
|
|
@@ -3667,10 +3754,10 @@ function parseArgs(finalConfig, remainingPositionals) {
|
|
|
3667
3754
|
}
|
|
3668
3755
|
function storeJson(config, saveconf) {
|
|
3669
3756
|
if (saveconf) {
|
|
3670
|
-
const
|
|
3757
|
+
const path7 = saveconf;
|
|
3671
3758
|
try {
|
|
3672
|
-
import_fs4.default.writeFileSync(
|
|
3673
|
-
logger.info(`Configuration saved to ${
|
|
3759
|
+
import_fs4.default.writeFileSync(path7, JSON.stringify(config, null, 2), { encoding: "utf-8", flag: "w" });
|
|
3760
|
+
logger.info(`Configuration saved to ${path7}`);
|
|
3674
3761
|
} catch (err) {
|
|
3675
3762
|
const msg = err instanceof Error ? err.message : String(err);
|
|
3676
3763
|
logger.error("Error loading configuration:", msg);
|
|
@@ -3720,7 +3807,7 @@ function parseAutoReconnect(finalConfig, values) {
|
|
|
3720
3807
|
}
|
|
3721
3808
|
return null;
|
|
3722
3809
|
}
|
|
3723
|
-
async function buildFinalConfig(values, positionals) {
|
|
3810
|
+
async function buildFinalConfig(values, positionals, baseConfig) {
|
|
3724
3811
|
let token;
|
|
3725
3812
|
let server;
|
|
3726
3813
|
let type;
|
|
@@ -3728,7 +3815,7 @@ async function buildFinalConfig(values, positionals) {
|
|
|
3728
3815
|
let qrCode = false;
|
|
3729
3816
|
let finalConfig = new Object();
|
|
3730
3817
|
let saveconf = isSaveConfOption(values);
|
|
3731
|
-
const configFromFile = loadJsonConfig(values);
|
|
3818
|
+
const configFromFile = baseConfig || loadJsonConfig(values);
|
|
3732
3819
|
const userParse = parseUsers(positionals, values.token);
|
|
3733
3820
|
token = userParse.token;
|
|
3734
3821
|
server = userParse.server;
|
|
@@ -3780,7 +3867,7 @@ async function buildFinalConfig(values, positionals) {
|
|
|
3780
3867
|
if (forceFlag || values.force) {
|
|
3781
3868
|
finalConfig.force = true;
|
|
3782
3869
|
}
|
|
3783
|
-
|
|
3870
|
+
parseArgs2(finalConfig, remainingPositionals);
|
|
3784
3871
|
storeJson(finalConfig, saveconf);
|
|
3785
3872
|
return finalConfig;
|
|
3786
3873
|
}
|
|
@@ -3811,74 +3898,6 @@ var init_buildConfig = __esm({
|
|
|
3811
3898
|
}
|
|
3812
3899
|
});
|
|
3813
3900
|
|
|
3814
|
-
// src/utils/parseArgs.ts
|
|
3815
|
-
function isAttachedReverseOrLocalFlag(arg) {
|
|
3816
|
-
return /^-[RL].+/.test(arg);
|
|
3817
|
-
}
|
|
3818
|
-
function shouldMergeReverseOrLocalFragment(current, next) {
|
|
3819
|
-
if (next.startsWith("-")) {
|
|
3820
|
-
return false;
|
|
3821
|
-
}
|
|
3822
|
-
if (next.startsWith(".")) {
|
|
3823
|
-
return true;
|
|
3824
|
-
}
|
|
3825
|
-
const body = current.slice(2);
|
|
3826
|
-
if (body.endsWith(":")) {
|
|
3827
|
-
return true;
|
|
3828
|
-
}
|
|
3829
|
-
if (body.includes("//") && !body.includes(":")) {
|
|
3830
|
-
return true;
|
|
3831
|
-
}
|
|
3832
|
-
return false;
|
|
3833
|
-
}
|
|
3834
|
-
function preprocessWindowsArgs(args) {
|
|
3835
|
-
if (os2.platform() !== "win32") {
|
|
3836
|
-
return args;
|
|
3837
|
-
}
|
|
3838
|
-
;
|
|
3839
|
-
const out = [];
|
|
3840
|
-
let i = 0;
|
|
3841
|
-
while (i < args.length) {
|
|
3842
|
-
const arg = args[i];
|
|
3843
|
-
if (isAttachedReverseOrLocalFlag(arg)) {
|
|
3844
|
-
let merged = arg;
|
|
3845
|
-
while (i + 1 < args.length && shouldMergeReverseOrLocalFragment(merged, args[i + 1])) {
|
|
3846
|
-
merged += args[i + 1];
|
|
3847
|
-
i++;
|
|
3848
|
-
}
|
|
3849
|
-
out.push(merged);
|
|
3850
|
-
i++;
|
|
3851
|
-
continue;
|
|
3852
|
-
}
|
|
3853
|
-
out.push(arg);
|
|
3854
|
-
i++;
|
|
3855
|
-
}
|
|
3856
|
-
return out;
|
|
3857
|
-
}
|
|
3858
|
-
function parseCliArgs(options) {
|
|
3859
|
-
const rawArgs = process.argv.slice(2);
|
|
3860
|
-
const processedArgs = preprocessWindowsArgs(rawArgs);
|
|
3861
|
-
const parsed = (0, import_util6.parseArgs)({
|
|
3862
|
-
args: processedArgs,
|
|
3863
|
-
options,
|
|
3864
|
-
allowPositionals: true
|
|
3865
|
-
});
|
|
3866
|
-
const hasAnyArgs = parsed.positionals.length > 0 || Object.values(parsed.values).some((v) => v !== void 0 && v !== false);
|
|
3867
|
-
return {
|
|
3868
|
-
...parsed,
|
|
3869
|
-
hasAnyArgs
|
|
3870
|
-
};
|
|
3871
|
-
}
|
|
3872
|
-
var import_util6, os2;
|
|
3873
|
-
var init_parseArgs = __esm({
|
|
3874
|
-
"src/utils/parseArgs.ts"() {
|
|
3875
|
-
"use strict";
|
|
3876
|
-
init_cjs_shims();
|
|
3877
|
-
import_util6 = require("util");
|
|
3878
|
-
os2 = __toESM(require("os"), 1);
|
|
3879
|
-
}
|
|
3880
|
-
});
|
|
3881
|
-
|
|
3882
3901
|
// src/utils/getFreePort.ts
|
|
3883
3902
|
function getFreePort(webDebugger) {
|
|
3884
3903
|
return new Promise((resolve, reject) => {
|
|
@@ -5492,6 +5511,600 @@ var init_starCli = __esm({
|
|
|
5492
5511
|
}
|
|
5493
5512
|
});
|
|
5494
5513
|
|
|
5514
|
+
// src/utils/configDir.ts
|
|
5515
|
+
function getPinggyConfigDir() {
|
|
5516
|
+
const platform2 = import_os2.default.platform();
|
|
5517
|
+
let baseDir;
|
|
5518
|
+
if (platform2 === "win32") {
|
|
5519
|
+
baseDir = process.env.APPDATA || import_path5.default.join(import_os2.default.homedir(), "AppData", "Roaming");
|
|
5520
|
+
} else {
|
|
5521
|
+
baseDir = process.env.XDG_CONFIG_HOME || import_path5.default.join(import_os2.default.homedir(), ".config");
|
|
5522
|
+
}
|
|
5523
|
+
return import_path5.default.join(baseDir, "pinggy");
|
|
5524
|
+
}
|
|
5525
|
+
function getTunnelConfigDir() {
|
|
5526
|
+
return import_path5.default.join(getPinggyConfigDir(), "tunnels");
|
|
5527
|
+
}
|
|
5528
|
+
function ensureTunnelConfigDir() {
|
|
5529
|
+
const dir = getTunnelConfigDir();
|
|
5530
|
+
import_fs5.default.mkdirSync(dir, { recursive: true });
|
|
5531
|
+
return dir;
|
|
5532
|
+
}
|
|
5533
|
+
var import_os2, import_path5, import_fs5;
|
|
5534
|
+
var init_configDir = __esm({
|
|
5535
|
+
"src/utils/configDir.ts"() {
|
|
5536
|
+
"use strict";
|
|
5537
|
+
init_cjs_shims();
|
|
5538
|
+
import_os2 = __toESM(require("os"), 1);
|
|
5539
|
+
import_path5 = __toESM(require("path"), 1);
|
|
5540
|
+
import_fs5 = __toESM(require("fs"), 1);
|
|
5541
|
+
}
|
|
5542
|
+
});
|
|
5543
|
+
|
|
5544
|
+
// src/cli/configStore.ts
|
|
5545
|
+
function buildFilename(name, configId) {
|
|
5546
|
+
return `${name}_${configId}.json`;
|
|
5547
|
+
}
|
|
5548
|
+
function sanitizeName(name) {
|
|
5549
|
+
return name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5550
|
+
}
|
|
5551
|
+
function validateName(name) {
|
|
5552
|
+
if (!name || name.trim().length === 0) {
|
|
5553
|
+
return new Error("Tunnel name cannot be empty.");
|
|
5554
|
+
}
|
|
5555
|
+
if (name.length > 128) {
|
|
5556
|
+
return new Error("Tunnel name cannot exceed 128 characters.");
|
|
5557
|
+
}
|
|
5558
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
5559
|
+
return new Error("Tunnel name can only contain alphanumeric characters, hyphens, and underscores.");
|
|
5560
|
+
}
|
|
5561
|
+
return null;
|
|
5562
|
+
}
|
|
5563
|
+
function readConfigFile(filePath) {
|
|
5564
|
+
try {
|
|
5565
|
+
const data = import_fs6.default.readFileSync(filePath, { encoding: "utf-8" });
|
|
5566
|
+
return JSON.parse(data);
|
|
5567
|
+
} catch (err) {
|
|
5568
|
+
logger.warn(`Failed to read config file ${filePath}:`, err);
|
|
5569
|
+
return null;
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5572
|
+
function writeConfigFile(filePath, config) {
|
|
5573
|
+
import_fs6.default.writeFileSync(filePath, JSON.stringify(config, null, 2), { encoding: "utf-8" });
|
|
5574
|
+
}
|
|
5575
|
+
function listSavedConfigs() {
|
|
5576
|
+
const dir = getTunnelConfigDir();
|
|
5577
|
+
if (!import_fs6.default.existsSync(dir)) {
|
|
5578
|
+
return [];
|
|
5579
|
+
}
|
|
5580
|
+
const files = import_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
5581
|
+
const configs = [];
|
|
5582
|
+
for (const file of files) {
|
|
5583
|
+
const config = readConfigFile(import_path6.default.join(dir, file));
|
|
5584
|
+
if (config && config.name && config.configId) {
|
|
5585
|
+
configs.push(config);
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
return configs;
|
|
5589
|
+
}
|
|
5590
|
+
function findConfigFile(nameOrId) {
|
|
5591
|
+
const dir = getTunnelConfigDir();
|
|
5592
|
+
if (!import_fs6.default.existsSync(dir)) return null;
|
|
5593
|
+
const files = import_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
5594
|
+
const sanitized = sanitizeName(nameOrId);
|
|
5595
|
+
const nameMatch = files.find((f) => f.startsWith(sanitized + "_"));
|
|
5596
|
+
if (nameMatch) {
|
|
5597
|
+
const filePath = import_path6.default.join(dir, nameMatch);
|
|
5598
|
+
const config = readConfigFile(filePath);
|
|
5599
|
+
if (config && config.name === nameOrId) return { filePath, config };
|
|
5600
|
+
}
|
|
5601
|
+
const idCandidates = files.filter((f) => {
|
|
5602
|
+
const withoutExt = f.replace(/\.json$/, "");
|
|
5603
|
+
const lastUnderscore = withoutExt.indexOf("_");
|
|
5604
|
+
if (lastUnderscore === -1) return false;
|
|
5605
|
+
const idPart = withoutExt.slice(lastUnderscore + 1);
|
|
5606
|
+
return idPart.startsWith(nameOrId);
|
|
5607
|
+
});
|
|
5608
|
+
if (idCandidates.length === 1) {
|
|
5609
|
+
const filePath = import_path6.default.join(dir, idCandidates[0]);
|
|
5610
|
+
const config = readConfigFile(filePath);
|
|
5611
|
+
if (config) return { filePath, config };
|
|
5612
|
+
}
|
|
5613
|
+
return null;
|
|
5614
|
+
}
|
|
5615
|
+
function findConfigByName(name) {
|
|
5616
|
+
const resolved = findConfigFile(name);
|
|
5617
|
+
return resolved?.config.name === name ? resolved.config : null;
|
|
5618
|
+
}
|
|
5619
|
+
function findConfig(nameOrId) {
|
|
5620
|
+
return findConfigFile(nameOrId)?.config ?? null;
|
|
5621
|
+
}
|
|
5622
|
+
function saveConfig(name, configId, tunnelConfig, autoStart = false) {
|
|
5623
|
+
const nameErr = validateName(name);
|
|
5624
|
+
if (nameErr) {
|
|
5625
|
+
throw nameErr;
|
|
5626
|
+
}
|
|
5627
|
+
const existing = findConfigByName(name);
|
|
5628
|
+
if (existing) {
|
|
5629
|
+
throw new Error(
|
|
5630
|
+
`A tunnel config with the name "${name}" already exists (configId: ${existing.configId}). Please use a different name.`
|
|
5631
|
+
);
|
|
5632
|
+
}
|
|
5633
|
+
const dir = ensureTunnelConfigDir();
|
|
5634
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5635
|
+
const saved = {
|
|
5636
|
+
name,
|
|
5637
|
+
configId,
|
|
5638
|
+
autoStart,
|
|
5639
|
+
createdAt: now,
|
|
5640
|
+
updatedAt: now,
|
|
5641
|
+
tunnelConfig
|
|
5642
|
+
};
|
|
5643
|
+
const filename = buildFilename(sanitizeName(name), configId);
|
|
5644
|
+
const filePath = import_path6.default.join(dir, filename);
|
|
5645
|
+
import_fs6.default.writeFileSync(filePath, JSON.stringify(saved, null, 2), { encoding: "utf-8" });
|
|
5646
|
+
logger.info(`Config "${name}" saved to ${filePath}`);
|
|
5647
|
+
return saved;
|
|
5648
|
+
}
|
|
5649
|
+
function deleteConfig(nameOrId) {
|
|
5650
|
+
const resolved = findConfigFile(nameOrId);
|
|
5651
|
+
if (!resolved) return null;
|
|
5652
|
+
import_fs6.default.unlinkSync(resolved.filePath);
|
|
5653
|
+
logger.info(`Config "${resolved.config.name}" deleted.`);
|
|
5654
|
+
return resolved.config.name;
|
|
5655
|
+
}
|
|
5656
|
+
function updateConfigAutoStart(nameOrId, autoStart) {
|
|
5657
|
+
const resolved = findConfigFile(nameOrId);
|
|
5658
|
+
if (!resolved) return null;
|
|
5659
|
+
resolved.config.autoStart = autoStart;
|
|
5660
|
+
resolved.config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5661
|
+
writeConfigFile(resolved.filePath, resolved.config);
|
|
5662
|
+
logger.info(`Config "${resolved.config.name}" auto-start set to ${autoStart}`);
|
|
5663
|
+
return resolved.config;
|
|
5664
|
+
}
|
|
5665
|
+
function updateTunnelConfig(nameOrId, tunnelConfig) {
|
|
5666
|
+
const resolved = findConfigFile(nameOrId);
|
|
5667
|
+
if (!resolved) return null;
|
|
5668
|
+
resolved.config.tunnelConfig = tunnelConfig;
|
|
5669
|
+
resolved.config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5670
|
+
writeConfigFile(resolved.filePath, resolved.config);
|
|
5671
|
+
logger.info(`Config "${resolved.config.name}" tunnel configuration updated`);
|
|
5672
|
+
return resolved.config;
|
|
5673
|
+
}
|
|
5674
|
+
function getAutoStartConfigs() {
|
|
5675
|
+
return listSavedConfigs().filter((c) => c.autoStart);
|
|
5676
|
+
}
|
|
5677
|
+
function printConfigList() {
|
|
5678
|
+
const configs = listSavedConfigs();
|
|
5679
|
+
if (configs.length === 0) {
|
|
5680
|
+
console.log(import_picocolors5.default.yellow("No saved tunnel configs found."));
|
|
5681
|
+
console.log(import_picocolors5.default.gray(`Config directory: ${getTunnelConfigDir()}`));
|
|
5682
|
+
return;
|
|
5683
|
+
}
|
|
5684
|
+
const nameW = 20;
|
|
5685
|
+
const idW = 12;
|
|
5686
|
+
const typeW = 8;
|
|
5687
|
+
const fwdW = 25;
|
|
5688
|
+
const serverW = 22;
|
|
5689
|
+
const autoW = 10;
|
|
5690
|
+
const header = import_picocolors5.default.bold("Name".padEnd(nameW)) + import_picocolors5.default.bold("Config ID".padEnd(idW)) + import_picocolors5.default.bold("Type".padEnd(typeW)) + import_picocolors5.default.bold("Forwarding".padEnd(fwdW)) + import_picocolors5.default.bold("Server".padEnd(serverW)) + import_picocolors5.default.bold("Auto-start".padEnd(autoW));
|
|
5691
|
+
console.log("\n" + header);
|
|
5692
|
+
console.log(import_picocolors5.default.gray("\u2500".repeat(nameW + idW + typeW + fwdW + serverW + autoW)));
|
|
5693
|
+
for (const c of configs) {
|
|
5694
|
+
const tc = c.tunnelConfig;
|
|
5695
|
+
const forwarding = Array.isArray(tc.forwarding) ? tc.forwarding[0]?.address : String(tc.forwarding || "");
|
|
5696
|
+
const type = (Array.isArray(tc.forwarding) ? tc.forwarding[0]?.type : void 0) || "http";
|
|
5697
|
+
const server = tc.serverAddress || "a.pinggy.io";
|
|
5698
|
+
const line = import_picocolors5.default.cyanBright(c.name.padEnd(nameW)) + import_picocolors5.default.gray(c.configId.slice(0, 8).padEnd(idW)) + type.padEnd(typeW) + forwarding.slice(0, fwdW - 2).padEnd(fwdW) + server.slice(0, serverW - 2).padEnd(serverW) + (c.autoStart ? import_picocolors5.default.green("yes") : import_picocolors5.default.gray("no")).padEnd(autoW);
|
|
5699
|
+
console.log(line);
|
|
5700
|
+
}
|
|
5701
|
+
console.log();
|
|
5702
|
+
}
|
|
5703
|
+
function printConfigDetail(config) {
|
|
5704
|
+
console.log(import_picocolors5.default.bold(`
|
|
5705
|
+
Tunnel Config: ${import_picocolors5.default.cyanBright(config.name)}`));
|
|
5706
|
+
console.log(import_picocolors5.default.gray("\u2500".repeat(40)));
|
|
5707
|
+
console.log(` Config ID: ${config.configId}`);
|
|
5708
|
+
console.log(` Auto-start: ${config.autoStart ? import_picocolors5.default.green("yes") : import_picocolors5.default.gray("no")}`);
|
|
5709
|
+
console.log(` Created: ${config.createdAt}`);
|
|
5710
|
+
console.log(` Updated: ${config.updatedAt}`);
|
|
5711
|
+
console.log(import_picocolors5.default.gray("\u2500".repeat(40)));
|
|
5712
|
+
console.log(` Server: ${config.tunnelConfig.serverAddress || "a.pinggy.io"}`);
|
|
5713
|
+
console.log(` Token: ${config.tunnelConfig.token ? "***" + config.tunnelConfig.token.slice(-4) : "(none)"}`);
|
|
5714
|
+
const fwd = config.tunnelConfig.forwarding;
|
|
5715
|
+
if (Array.isArray(fwd)) {
|
|
5716
|
+
const defaultFwds = [];
|
|
5717
|
+
const customFwds = [];
|
|
5718
|
+
for (const f of fwd) {
|
|
5719
|
+
if (typeof f === "string") {
|
|
5720
|
+
defaultFwds.push(f);
|
|
5721
|
+
} else if (f.listenAddress) {
|
|
5722
|
+
customFwds.push(f);
|
|
5723
|
+
} else {
|
|
5724
|
+
defaultFwds.push(f);
|
|
5725
|
+
}
|
|
5726
|
+
}
|
|
5727
|
+
for (const f of defaultFwds) {
|
|
5728
|
+
const addr = typeof f === "string" ? f : `${f.address} (${f.type || "http"})`;
|
|
5729
|
+
console.log(` Forwarding: ${addr}`);
|
|
5730
|
+
if (config.tunnelConfig.webDebugger) {
|
|
5731
|
+
console.log(` Debugger: ${config.tunnelConfig.webDebugger}`);
|
|
5732
|
+
}
|
|
5733
|
+
}
|
|
5734
|
+
if (customFwds.length > 0) {
|
|
5735
|
+
console.log(import_picocolors5.default.gray("\u2500".repeat(40)));
|
|
5736
|
+
console.log(import_picocolors5.default.bold(" Domain Mappings:"));
|
|
5737
|
+
for (const f of customFwds) {
|
|
5738
|
+
if (typeof f === "string") continue;
|
|
5739
|
+
const domain = f.listenAddress;
|
|
5740
|
+
const target = f.address;
|
|
5741
|
+
const type = f.type || "http";
|
|
5742
|
+
console.log(` ${import_picocolors5.default.cyanBright(domain)} \u2192 ${target} (${type})`);
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
} else if (fwd) {
|
|
5746
|
+
console.log(` Forwarding: ${fwd}`);
|
|
5747
|
+
}
|
|
5748
|
+
console.log();
|
|
5749
|
+
}
|
|
5750
|
+
var import_fs6, import_path6, import_picocolors5;
|
|
5751
|
+
var init_configStore = __esm({
|
|
5752
|
+
"src/cli/configStore.ts"() {
|
|
5753
|
+
"use strict";
|
|
5754
|
+
init_cjs_shims();
|
|
5755
|
+
import_fs6 = __toESM(require("fs"), 1);
|
|
5756
|
+
import_path6 = __toESM(require("path"), 1);
|
|
5757
|
+
init_configDir();
|
|
5758
|
+
init_logger();
|
|
5759
|
+
import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
5760
|
+
}
|
|
5761
|
+
});
|
|
5762
|
+
|
|
5763
|
+
// src/cli/buildAndStartTunnel.ts
|
|
5764
|
+
async function buildAndStartTunnel(values, positionals, manager) {
|
|
5765
|
+
await initRemoteManagement(values);
|
|
5766
|
+
logger.debug("Building final config from CLI values and positionals", { values, positionals });
|
|
5767
|
+
const finalConfig = await buildFinalConfig(values, positionals);
|
|
5768
|
+
logger.debug("Final configuration built", finalConfig);
|
|
5769
|
+
if (values.save) {
|
|
5770
|
+
const name = values.name;
|
|
5771
|
+
if (!name) {
|
|
5772
|
+
printer_default.error("--save requires --name to specify a name for the tunnel config.");
|
|
5773
|
+
process.exit(1);
|
|
5774
|
+
}
|
|
5775
|
+
const nameErr = validateName(name);
|
|
5776
|
+
if (nameErr) {
|
|
5777
|
+
printer_default.error(nameErr.message);
|
|
5778
|
+
process.exit(1);
|
|
5779
|
+
}
|
|
5780
|
+
const autoStart = !!values.auto;
|
|
5781
|
+
saveConfig(name, finalConfig.configId, finalConfig, autoStart);
|
|
5782
|
+
printer_default.success(`Config "${name}" saved.`);
|
|
5783
|
+
}
|
|
5784
|
+
await startCli(finalConfig, manager);
|
|
5785
|
+
}
|
|
5786
|
+
async function initRemoteManagement(values) {
|
|
5787
|
+
const parseResult = await parseRemoteManagement(values);
|
|
5788
|
+
if (parseResult?.ok === false) {
|
|
5789
|
+
logger.error("Failed to initiate remote management:", parseResult.error);
|
|
5790
|
+
printer_default.fatal(parseResult.error);
|
|
5791
|
+
}
|
|
5792
|
+
}
|
|
5793
|
+
var init_buildAndStartTunnel = __esm({
|
|
5794
|
+
"src/cli/buildAndStartTunnel.ts"() {
|
|
5795
|
+
"use strict";
|
|
5796
|
+
init_cjs_shims();
|
|
5797
|
+
init_logger();
|
|
5798
|
+
init_remoteManagement();
|
|
5799
|
+
init_buildConfig();
|
|
5800
|
+
init_starCli();
|
|
5801
|
+
init_printer();
|
|
5802
|
+
init_configStore();
|
|
5803
|
+
}
|
|
5804
|
+
});
|
|
5805
|
+
|
|
5806
|
+
// src/cli/subcommands.ts
|
|
5807
|
+
function isSubcommand(rawArgs) {
|
|
5808
|
+
return rawArgs.length > 0 && SUBCOMMANDS.has(rawArgs[0]);
|
|
5809
|
+
}
|
|
5810
|
+
async function handleSubcommand(rawArgs, manager) {
|
|
5811
|
+
const sub = rawArgs[0];
|
|
5812
|
+
const rest = rawArgs.slice(1);
|
|
5813
|
+
switch (sub) {
|
|
5814
|
+
case "config":
|
|
5815
|
+
await handleConfig(rest);
|
|
5816
|
+
return;
|
|
5817
|
+
case "start":
|
|
5818
|
+
await handleStart(rest, manager);
|
|
5819
|
+
return;
|
|
5820
|
+
}
|
|
5821
|
+
}
|
|
5822
|
+
async function handleConfig(args) {
|
|
5823
|
+
if (args.length === 0) {
|
|
5824
|
+
printConfigHelp();
|
|
5825
|
+
return;
|
|
5826
|
+
}
|
|
5827
|
+
const verb = args[0];
|
|
5828
|
+
const rest = args.slice(1);
|
|
5829
|
+
switch (verb) {
|
|
5830
|
+
case "list":
|
|
5831
|
+
case "ls":
|
|
5832
|
+
printConfigList();
|
|
5833
|
+
return;
|
|
5834
|
+
case "show": {
|
|
5835
|
+
const names = requireNames(rest, "config show");
|
|
5836
|
+
for (const name of names) {
|
|
5837
|
+
const saved2 = resolveConfig(name);
|
|
5838
|
+
if (saved2) printConfigDetail(saved2);
|
|
5839
|
+
}
|
|
5840
|
+
return;
|
|
5841
|
+
}
|
|
5842
|
+
case "save": {
|
|
5843
|
+
const name = requireName(rest, "config save");
|
|
5844
|
+
await handleConfigSave(name, rest.slice(1));
|
|
5845
|
+
return;
|
|
5846
|
+
}
|
|
5847
|
+
case "delete": {
|
|
5848
|
+
const names = requireNames(rest, "config delete");
|
|
5849
|
+
for (const name of names) {
|
|
5850
|
+
const deletedName = deleteConfig(name);
|
|
5851
|
+
if (deletedName) {
|
|
5852
|
+
printer_default.success(`Config "${deletedName}" deleted.`);
|
|
5853
|
+
} else {
|
|
5854
|
+
printer_default.error(`No config found matching "${name}". Use: pinggy config list`);
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5857
|
+
return;
|
|
5858
|
+
}
|
|
5859
|
+
case "update": {
|
|
5860
|
+
const name = requireName(rest, "config update");
|
|
5861
|
+
await handleConfigUpdate(name, rest.slice(1));
|
|
5862
|
+
return;
|
|
5863
|
+
}
|
|
5864
|
+
case "auto": {
|
|
5865
|
+
const names = requireNames(rest, "config auto");
|
|
5866
|
+
for (const name of names) {
|
|
5867
|
+
const updated = updateConfigAutoStart(name, true);
|
|
5868
|
+
if (updated) {
|
|
5869
|
+
printer_default.success(`Config "${updated.name}" auto-start set to on.`);
|
|
5870
|
+
} else {
|
|
5871
|
+
printer_default.error(`No config found matching "${name}". Use: pinggy config list`);
|
|
5872
|
+
}
|
|
5873
|
+
}
|
|
5874
|
+
return;
|
|
5875
|
+
}
|
|
5876
|
+
case "noauto": {
|
|
5877
|
+
const names = requireNames(rest, "config noauto");
|
|
5878
|
+
for (const name of names) {
|
|
5879
|
+
const updated = updateConfigAutoStart(name, false);
|
|
5880
|
+
if (updated) {
|
|
5881
|
+
printer_default.success(`Config "${updated.name}" auto-start set to off.`);
|
|
5882
|
+
} else {
|
|
5883
|
+
printer_default.error(`No config found matching "${name}". Use: pinggy config list`);
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5886
|
+
return;
|
|
5887
|
+
}
|
|
5888
|
+
default:
|
|
5889
|
+
const saved = resolveConfig(verb);
|
|
5890
|
+
if (saved) printConfigDetail(saved);
|
|
5891
|
+
return;
|
|
5892
|
+
}
|
|
5893
|
+
}
|
|
5894
|
+
async function handleConfigSave(name, remainingArgs) {
|
|
5895
|
+
const nameErr = validateName(name);
|
|
5896
|
+
if (nameErr) {
|
|
5897
|
+
printer_default.error(nameErr.message);
|
|
5898
|
+
process.exit(1);
|
|
5899
|
+
}
|
|
5900
|
+
const { values, positionals } = parseCliArgs(cliOptions, remainingArgs);
|
|
5901
|
+
const autoStart = !!values.auto;
|
|
5902
|
+
logger.debug("Building config for save", { name, values, positionals });
|
|
5903
|
+
const finalConfig = await buildFinalConfig(values, positionals);
|
|
5904
|
+
saveConfig(name, finalConfig.configId, finalConfig, autoStart);
|
|
5905
|
+
printer_default.success(`Config "${name}" saved.`);
|
|
5906
|
+
}
|
|
5907
|
+
async function handleConfigUpdate(nameOrId, remainingArgs) {
|
|
5908
|
+
const saved = resolveConfig(nameOrId);
|
|
5909
|
+
if (!saved) return;
|
|
5910
|
+
const { values, positionals } = parseCliArgs(cliOptions, remainingArgs);
|
|
5911
|
+
logger.debug("Building updated config", { nameOrId, values, positionals });
|
|
5912
|
+
const updatedConfig = await buildFinalConfig(values, positionals, saved.tunnelConfig);
|
|
5913
|
+
const result = updateTunnelConfig(nameOrId, updatedConfig);
|
|
5914
|
+
if (result) {
|
|
5915
|
+
printer_default.success(`Config "${result.name}" updated.`);
|
|
5916
|
+
printConfigDetail(result);
|
|
5917
|
+
} else {
|
|
5918
|
+
printer_default.error(`Failed to update config "${nameOrId}".`);
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5921
|
+
async function handleStart(args, manager) {
|
|
5922
|
+
const startAll = args.includes("--all");
|
|
5923
|
+
const argsWithoutAll = args.filter((a) => a !== "--all");
|
|
5924
|
+
const names = [];
|
|
5925
|
+
let i = 0;
|
|
5926
|
+
while (i < argsWithoutAll.length && !argsWithoutAll[i].startsWith("-")) {
|
|
5927
|
+
names.push(argsWithoutAll[i]);
|
|
5928
|
+
i++;
|
|
5929
|
+
}
|
|
5930
|
+
const flagArgs = argsWithoutAll.slice(i);
|
|
5931
|
+
const { values, positionals } = parseCliArgs(cliOptions, flagArgs);
|
|
5932
|
+
configureLogger(values);
|
|
5933
|
+
if (startAll) {
|
|
5934
|
+
await initRemoteManagementBackground(values);
|
|
5935
|
+
await startAutoStartTunnels(manager);
|
|
5936
|
+
return;
|
|
5937
|
+
}
|
|
5938
|
+
if (names.length === 0) {
|
|
5939
|
+
printStartHelp();
|
|
5940
|
+
return;
|
|
5941
|
+
}
|
|
5942
|
+
const resolved = [];
|
|
5943
|
+
for (const name of names) {
|
|
5944
|
+
const saved = resolveConfig(name);
|
|
5945
|
+
if (!saved) return;
|
|
5946
|
+
resolved.push(saved);
|
|
5947
|
+
}
|
|
5948
|
+
if (resolved.length > 1 && flagArgs.length > 0) {
|
|
5949
|
+
printer_default.error("Runtime overrides (-l, --type, etc.) can only be used when starting a single tunnel.");
|
|
5950
|
+
printer_default.print(" Start one tunnel: pinggy start my-tunnel -l 4000");
|
|
5951
|
+
printer_default.print(" Or update first: pinggy config update my-tunnel -l 4000");
|
|
5952
|
+
return;
|
|
5953
|
+
}
|
|
5954
|
+
await initRemoteManagementBackground(values);
|
|
5955
|
+
if (resolved.length === 1) {
|
|
5956
|
+
const saved = resolved[0];
|
|
5957
|
+
logger.debug("Building config with overrides", { name: saved.name });
|
|
5958
|
+
const finalConfig = await buildFinalConfig(values, positionals, saved.tunnelConfig);
|
|
5959
|
+
finalConfig.configId = saved.configId;
|
|
5960
|
+
await startCli(finalConfig, manager);
|
|
5961
|
+
} else {
|
|
5962
|
+
await startNamedTunnels(resolved, manager);
|
|
5963
|
+
}
|
|
5964
|
+
}
|
|
5965
|
+
async function startAutoStartTunnels(manager) {
|
|
5966
|
+
const configs = getAutoStartConfigs();
|
|
5967
|
+
if (configs.length === 0) {
|
|
5968
|
+
printer_default.warn("No configs marked for auto-start. Use: pinggy config auto <name>");
|
|
5969
|
+
return;
|
|
5970
|
+
}
|
|
5971
|
+
printer_default.print(import_picocolors6.default.cyanBright(`Starting ${configs.length} auto-start tunnel(s)...`));
|
|
5972
|
+
for (const saved of configs) {
|
|
5973
|
+
await startSavedTunnel(saved, manager);
|
|
5974
|
+
}
|
|
5975
|
+
printer_default.print(import_picocolors6.default.gray("\nAll auto-start tunnels launched. Press Ctrl+C to stop.\n"));
|
|
5976
|
+
await new Promise(() => {
|
|
5977
|
+
});
|
|
5978
|
+
}
|
|
5979
|
+
async function startNamedTunnels(configs, manager) {
|
|
5980
|
+
printer_default.print(import_picocolors6.default.cyanBright(`Starting ${configs.length} tunnel(s)...`));
|
|
5981
|
+
for (const saved of configs) {
|
|
5982
|
+
await startSavedTunnel(saved, manager);
|
|
5983
|
+
}
|
|
5984
|
+
printer_default.print(import_picocolors6.default.gray("\nAll tunnels launched. Press Ctrl+C to stop.\n"));
|
|
5985
|
+
await new Promise(() => {
|
|
5986
|
+
});
|
|
5987
|
+
}
|
|
5988
|
+
async function startSavedTunnel(saved, manager) {
|
|
5989
|
+
const config = {
|
|
5990
|
+
...saved.tunnelConfig,
|
|
5991
|
+
configId: saved.configId,
|
|
5992
|
+
name: saved.name,
|
|
5993
|
+
optional: {
|
|
5994
|
+
...saved.tunnelConfig.optional,
|
|
5995
|
+
noTui: true
|
|
5996
|
+
}
|
|
5997
|
+
};
|
|
5998
|
+
try {
|
|
5999
|
+
const tunnel = await manager.createTunnel(config);
|
|
6000
|
+
await manager.startTunnel(tunnel.tunnelid);
|
|
6001
|
+
const urls = await manager.getTunnelUrls(tunnel.tunnelid);
|
|
6002
|
+
printer_default.success(`"${saved.name}" started`);
|
|
6003
|
+
(urls ?? []).forEach(
|
|
6004
|
+
(url) => printer_default.print(" " + import_picocolors6.default.magentaBright(url))
|
|
6005
|
+
);
|
|
6006
|
+
manager.registerWorkerErrorListner(tunnel.tunnelid, (_id, error) => {
|
|
6007
|
+
printer_default.error(`[${saved.name}] Fatal: ${error.message}`);
|
|
6008
|
+
});
|
|
6009
|
+
manager.registerDisconnectListener(tunnel.tunnelid, async (_id, error, messages) => {
|
|
6010
|
+
if (error) printer_default.warn(`[${saved.name}] Disconnected: ${error}`);
|
|
6011
|
+
messages?.forEach((m) => printer_default.warn(`[${saved.name}] ${m}`));
|
|
6012
|
+
});
|
|
6013
|
+
manager.registerReconnectingListener(tunnel.tunnelid, (_id, retryCnt) => {
|
|
6014
|
+
printer_default.print(import_picocolors6.default.gray(`[${saved.name}] Reconnecting (attempt #${retryCnt})...`));
|
|
6015
|
+
});
|
|
6016
|
+
manager.registerReconnectionCompletedListener(tunnel.tunnelid, async (_id, urls2) => {
|
|
6017
|
+
printer_default.success(`[${saved.name}] Reconnected`);
|
|
6018
|
+
(urls2 ?? []).forEach(
|
|
6019
|
+
(url) => printer_default.print(" " + import_picocolors6.default.magentaBright(url))
|
|
6020
|
+
);
|
|
6021
|
+
});
|
|
6022
|
+
manager.registerReconnectionFailedListener(tunnel.tunnelid, (_id, retryCnt) => {
|
|
6023
|
+
printer_default.error(`[${saved.name}] Reconnection failed after ${retryCnt} attempts`);
|
|
6024
|
+
});
|
|
6025
|
+
} catch (err) {
|
|
6026
|
+
printer_default.error(`[${saved.name}] Failed to start: ${err.message || err}`);
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
function resolveConfig(nameOrId) {
|
|
6030
|
+
const saved = findConfig(nameOrId);
|
|
6031
|
+
if (!saved) {
|
|
6032
|
+
printer_default.error(`No config found matching "${nameOrId}". Use: pinggy config list`);
|
|
6033
|
+
return null;
|
|
6034
|
+
}
|
|
6035
|
+
return saved;
|
|
6036
|
+
}
|
|
6037
|
+
function requireName(args, command) {
|
|
6038
|
+
if (args.length === 0 || args[0].startsWith("-")) {
|
|
6039
|
+
printer_default.error(`Tunnel name is required. Usage: pinggy ${command} <name>`);
|
|
6040
|
+
process.exit(1);
|
|
6041
|
+
}
|
|
6042
|
+
return args[0];
|
|
6043
|
+
}
|
|
6044
|
+
function requireNames(args, command) {
|
|
6045
|
+
const names = [];
|
|
6046
|
+
for (const arg of args) {
|
|
6047
|
+
if (arg.startsWith("-")) break;
|
|
6048
|
+
names.push(arg);
|
|
6049
|
+
}
|
|
6050
|
+
if (names.length === 0) {
|
|
6051
|
+
printer_default.error(`At least one tunnel name is required. Usage: pinggy ${command} <name> [name2 ...]`);
|
|
6052
|
+
process.exit(1);
|
|
6053
|
+
}
|
|
6054
|
+
return names;
|
|
6055
|
+
}
|
|
6056
|
+
async function initRemoteManagementBackground(values) {
|
|
6057
|
+
const rmToken = values["remote-management"];
|
|
6058
|
+
if (typeof rmToken === "string" && rmToken.trim().length > 0) {
|
|
6059
|
+
const manageHost = values["manage"];
|
|
6060
|
+
try {
|
|
6061
|
+
await startRemoteManagement({
|
|
6062
|
+
apiKey: rmToken,
|
|
6063
|
+
serverUrl: buildRemoteManagementWsUrl(manageHost)
|
|
6064
|
+
});
|
|
6065
|
+
} catch (e) {
|
|
6066
|
+
logger.error("Failed to initiate remote management:", e);
|
|
6067
|
+
printer_default.fatal(e);
|
|
6068
|
+
}
|
|
6069
|
+
}
|
|
6070
|
+
}
|
|
6071
|
+
function printConfigHelp() {
|
|
6072
|
+
console.log("\nUsage: pinggy config <command> [name] [options]\n");
|
|
6073
|
+
console.log("Commands:");
|
|
6074
|
+
console.log(" list List all saved configs");
|
|
6075
|
+
console.log(" show <name> Show config details");
|
|
6076
|
+
console.log(" save <name> [tunnel flags] Save a tunnel config");
|
|
6077
|
+
console.log(" update <name> [tunnel flags] Update a saved config");
|
|
6078
|
+
console.log(" delete <name> Delete a saved config");
|
|
6079
|
+
console.log(" auto <name> Enable auto-start");
|
|
6080
|
+
console.log(" noauto <name> Disable auto-start\n");
|
|
6081
|
+
}
|
|
6082
|
+
function printStartHelp() {
|
|
6083
|
+
console.log("\nUsage: pinggy start <name> [options]\n");
|
|
6084
|
+
console.log("Examples:");
|
|
6085
|
+
console.log(" pinggy start my-tunnel Start a saved tunnel");
|
|
6086
|
+
console.log(" pinggy start my-tunnel -l 4000 Start with override");
|
|
6087
|
+
console.log(" pinggy start tunnela tunnelb Start multiple tunnels");
|
|
6088
|
+
console.log(" pinggy start --all Start all auto-start tunnels\n");
|
|
6089
|
+
}
|
|
6090
|
+
var import_picocolors6, SUBCOMMANDS;
|
|
6091
|
+
var init_subcommands = __esm({
|
|
6092
|
+
"src/cli/subcommands.ts"() {
|
|
6093
|
+
"use strict";
|
|
6094
|
+
init_cjs_shims();
|
|
6095
|
+
init_options();
|
|
6096
|
+
init_parseArgs();
|
|
6097
|
+
init_buildConfig();
|
|
6098
|
+
init_starCli();
|
|
6099
|
+
init_printer();
|
|
6100
|
+
init_logger();
|
|
6101
|
+
import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
6102
|
+
init_configStore();
|
|
6103
|
+
init_remoteManagement();
|
|
6104
|
+
SUBCOMMANDS = /* @__PURE__ */ new Set(["config", "start"]);
|
|
6105
|
+
}
|
|
6106
|
+
});
|
|
6107
|
+
|
|
5495
6108
|
// src/main.ts
|
|
5496
6109
|
var main_exports = {};
|
|
5497
6110
|
__export(main_exports, {
|
|
@@ -5505,8 +6118,7 @@ __export(main_exports, {
|
|
|
5505
6118
|
});
|
|
5506
6119
|
async function main() {
|
|
5507
6120
|
try {
|
|
5508
|
-
const
|
|
5509
|
-
configureLogger(values);
|
|
6121
|
+
const rawArgs = process.argv.slice(2);
|
|
5510
6122
|
const manager = TunnelManager.getInstance();
|
|
5511
6123
|
process.on("SIGINT", () => {
|
|
5512
6124
|
logger.info("SIGINT received: stopping tunnels and exiting");
|
|
@@ -5515,6 +6127,12 @@ async function main() {
|
|
|
5515
6127
|
console.log("Tunnels stopped. Exiting.");
|
|
5516
6128
|
process.exit(0);
|
|
5517
6129
|
});
|
|
6130
|
+
if (isSubcommand(rawArgs)) {
|
|
6131
|
+
await handleSubcommand(rawArgs, manager);
|
|
6132
|
+
return;
|
|
6133
|
+
}
|
|
6134
|
+
const { values, positionals, hasAnyArgs } = parseCliArgs(cliOptions);
|
|
6135
|
+
configureLogger(values);
|
|
5518
6136
|
if (!hasAnyArgs || values.help) {
|
|
5519
6137
|
printHelpMessage();
|
|
5520
6138
|
return;
|
|
@@ -5523,21 +6141,13 @@ async function main() {
|
|
|
5523
6141
|
printer_default.print(`Pinggy CLI version: ${getVersion()}`);
|
|
5524
6142
|
return;
|
|
5525
6143
|
}
|
|
5526
|
-
|
|
5527
|
-
if (parseResult?.ok === false) {
|
|
5528
|
-
logger.error("Failed to initiate remote management:", parseResult.error);
|
|
5529
|
-
printer_default.fatal(parseResult.error);
|
|
5530
|
-
}
|
|
5531
|
-
logger.debug("Building final config from CLI values and positionals", { values, positionals });
|
|
5532
|
-
const finalConfig = await buildFinalConfig(values, positionals);
|
|
5533
|
-
logger.debug("Final configuration built", finalConfig);
|
|
5534
|
-
await startCli(finalConfig, manager);
|
|
6144
|
+
await buildAndStartTunnel(values, positionals, manager);
|
|
5535
6145
|
} catch (error) {
|
|
5536
6146
|
logger.error("Unhandled error in CLI:", error);
|
|
5537
6147
|
printer_default.fatal(error);
|
|
5538
6148
|
}
|
|
5539
6149
|
}
|
|
5540
|
-
var import_url2, import_process,
|
|
6150
|
+
var import_url2, import_process, import_fs7, currentFile, entryFile;
|
|
5541
6151
|
var init_main = __esm({
|
|
5542
6152
|
"src/main.ts"() {
|
|
5543
6153
|
"use strict";
|
|
@@ -5545,23 +6155,22 @@ var init_main = __esm({
|
|
|
5545
6155
|
init_TunnelManager();
|
|
5546
6156
|
init_help();
|
|
5547
6157
|
init_options();
|
|
5548
|
-
init_buildConfig();
|
|
5549
6158
|
init_logger();
|
|
5550
|
-
init_remoteManagement();
|
|
5551
6159
|
init_parseArgs();
|
|
5552
6160
|
init_printer();
|
|
5553
|
-
init_starCli();
|
|
5554
6161
|
init_util();
|
|
5555
6162
|
init_handler();
|
|
5556
6163
|
import_url2 = require("url");
|
|
5557
6164
|
import_process = require("process");
|
|
5558
|
-
|
|
6165
|
+
import_fs7 = require("fs");
|
|
5559
6166
|
init_logger();
|
|
5560
6167
|
init_remoteManagement();
|
|
6168
|
+
init_buildAndStartTunnel();
|
|
6169
|
+
init_subcommands();
|
|
5561
6170
|
currentFile = (0, import_url2.fileURLToPath)(importMetaUrl);
|
|
5562
6171
|
entryFile = null;
|
|
5563
6172
|
try {
|
|
5564
|
-
entryFile = import_process.argv[1] ? (0,
|
|
6173
|
+
entryFile = import_process.argv[1] ? (0, import_fs7.realpathSync)(import_process.argv[1]) : null;
|
|
5565
6174
|
} catch (e) {
|
|
5566
6175
|
entryFile = null;
|
|
5567
6176
|
}
|