pinggy 0.4.6 → 0.4.8

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 CHANGED
@@ -11,6 +11,8 @@ Create secure, shareable tunnels to your localhost and manage them from the comm
11
11
  - Remote management via secure WebSocket connection (works with Pinggy Dashboard)
12
12
  - Configurable logging to file and/or stdout
13
13
  - Save and load configuration files
14
+ - Config store for saving, listing, updating, and starting named tunnel configs
15
+ - Auto-start support for launching saved tunnels automatically
14
16
  - Simple file server mode for quickly sharing local files
15
17
  - Built-in TUI (Text User Interface) for viewing tunnel statistics, requests, and responses in real time
16
18
 
@@ -95,11 +97,11 @@ The CLI supports both SSH-style flags and more descriptive long flags. Below is
95
97
  | `--logfile` | Path to log file |
96
98
  | `--v` | Print logs to stdout |
97
99
  | `--vv` | Detailed logs (Node.js SDK + Libpinggy) |
98
- | `--vvv` | Enable logs from CLI, SDK, and Libpinggy |Libpinggy.
100
+ | `--vvv` | Enable logs from CLI, SDK, and Libpinggy |
99
101
 
100
102
  ---
101
103
 
102
- ### **Config**
104
+ ### **Config (File-based)**
103
105
  | Flag | Description |
104
106
  |------|-------------|
105
107
  | `--saveconf <file>` | Create configuration file with provided options |
@@ -199,6 +201,94 @@ pinggy --conf ./myconfig.json -p 8080
199
201
  ```
200
202
 
201
203
 
204
+ ## Config management
205
+
206
+ The CLI includes a built-in config store for saving, listing, and starting tunnel configurations. Configs are persisted as JSON files in your platform's config directory (`~/.config/pinggy/tunnels/` on Linux/macOS, `%APPDATA%/pinggy/tunnels/` on Windows).
207
+
208
+ ### Save a tunnel config
209
+ ```bash
210
+ pinggy config save my-tunnel -l 3000 token@pro.pinggy.io
211
+ ```
212
+
213
+ ### Save with auto-start enabled
214
+ ```bash
215
+ pinggy config save my-tunnel --auto -l 3000
216
+ ```
217
+
218
+ ### List all saved configs
219
+ ```bash
220
+ pinggy config list
221
+ ```
222
+
223
+ ### View details of a saved config
224
+ ```bash
225
+ pinggy config show my-tunnel
226
+ pinggy config show my-tunnel other-tunnel # View multiple configs
227
+ ```
228
+
229
+ ### Update a saved config
230
+ ```bash
231
+ pinggy config update my-tunnel -l 4000
232
+ ```
233
+
234
+ ### Enable or disable auto-start
235
+ ```bash
236
+ pinggy config auto my-tunnel
237
+ pinggy config noauto my-tunnel
238
+ pinggy config auto tunnel1 tunnel2 # Multiple configs at once
239
+ ```
240
+
241
+ ### Delete a saved config
242
+ ```bash
243
+ pinggy config delete my-tunnel
244
+ pinggy config delete tunnel1 tunnel2 # Delete multiple
245
+ ```
246
+
247
+ ### Shorthand: view config details
248
+ ```bash
249
+ pinggy config my-tunnel # Same as: pinggy config show my-tunnel
250
+ ```
251
+
252
+ Configs can be looked up by name (exact match) or by configId prefix (partial match).
253
+
254
+
255
+ ## Starting saved tunnels
256
+
257
+ ### Start a saved tunnel
258
+ ```bash
259
+ pinggy start my-tunnel
260
+ ```
261
+
262
+ ### Start with runtime overrides
263
+ ```bash
264
+ pinggy start my-tunnel -l 4000
265
+ ```
266
+
267
+ ### Start multiple tunnels
268
+ ```bash
269
+ pinggy start tunnel1 tunnel2
270
+ ```
271
+
272
+ ### Start all auto-start tunnels
273
+ ```bash
274
+ pinggy start --all
275
+ ```
276
+
277
+ ### Start with remote management
278
+ ```bash
279
+ pinggy start --all --remote-management <API_KEY>
280
+ pinggy start tunnel1 tunnel2 --remote-management <API_KEY>
281
+ ```
282
+
283
+ ### Start with logging enabled
284
+ ```bash
285
+ pinggy start my-tunnel --vvv
286
+ pinggy start --all --logfile /tmp/pinggy.log --loglevel DEBUG
287
+ ```
288
+
289
+ > **Note:** Runtime overrides (`-l`, `--type`, `--token`, etc.) can only be used when starting a single tunnel. For multiple tunnels, update the saved config first with `pinggy config update`.
290
+
291
+
202
292
  ## File server mode
203
293
  Serve a local directory quickly over a tunnel:
204
294
  ` pinggy --serve /path/to/files`
@@ -216,5 +306,3 @@ This package follows semantic versioning. See package.json for the current versi
216
306
 
217
307
  ## License
218
308
  Apache License Version 2.0
219
-
220
-
@@ -194,9 +194,10 @@ var TunnelManager = class _TunnelManager {
194
194
  * status information, and statistics
195
195
  */
196
196
  async createTunnel(config) {
197
- const { configId, tunnelid: requestedTunnelId, tunnelName, name, serve } = config;
197
+ const { configId, tunnelid: requestedTunnelId, tunnelName, name } = config;
198
198
  const tunnelid = requestedTunnelId || getRandomId();
199
199
  const autoReconnect = config.autoReconnect || false;
200
+ const serve = this.resolveServePath(config);
200
201
  if (!configId || typeof configId !== "string" || configId.trim() === "") {
201
202
  throw new Error("configId is required and must be a non-empty string");
202
203
  }
@@ -283,8 +284,11 @@ var TunnelManager = class _TunnelManager {
283
284
  throw error;
284
285
  }
285
286
  logger.info("Tunnel started", { tunnelId, urls });
287
+ logger.info("Checking serve config for tunnel", { tunnelId, serve: managed.serve });
286
288
  if (managed.serve) {
287
289
  this.startStaticFileServer(managed);
290
+ } else {
291
+ logger.debug("No serve path configured, skipping static file server", { tunnelId });
288
292
  }
289
293
  try {
290
294
  const startListeners = this.tunnelStartListeners.get(tunnelId);
@@ -616,6 +620,7 @@ var TunnelManager = class _TunnelManager {
616
620
  const currentTunnelName = existingTunnel.tunnelName;
617
621
  const currentServe = existingTunnel.serve;
618
622
  const currentAutoReconnect = existingTunnel.autoReconnect || false;
623
+ const requestedServe = this.resolveServePath(newConfig);
619
624
  try {
620
625
  if (!isStopped) {
621
626
  existingTunnel.instance.stop();
@@ -626,9 +631,9 @@ var TunnelManager = class _TunnelManager {
626
631
  ...newConfig,
627
632
  configId,
628
633
  tunnelName: newTunnelName !== void 0 ? newTunnelName : currentTunnelName,
629
- serve: newConfig.serve !== void 0 ? newConfig.serve : currentServe
634
+ serve: requestedServe !== void 0 ? requestedServe : currentServe
630
635
  };
631
- const effectiveServe = newConfig.serve !== void 0 ? newConfig.serve : currentServe;
636
+ const effectiveServe = requestedServe !== void 0 ? requestedServe : currentServe;
632
637
  const effectiveTunnelName = newTunnelName !== void 0 ? newTunnelName : currentTunnelName;
633
638
  let configWithForwarding;
634
639
  const newTunnel = await this._createTunnelWithProcessedConfig({
@@ -1387,21 +1392,35 @@ var TunnelManager = class _TunnelManager {
1387
1392
  const parsed = typeof value === "number" ? value : parseInt(String(value), 10);
1388
1393
  return isNaN(parsed) ? 0 : parsed;
1389
1394
  }
1395
+ /**
1396
+ * Read serve path only from config.optional.serve.
1397
+ */
1398
+ resolveServePath(config) {
1399
+ const optional = config.optional;
1400
+ const servePath = optional?.serve;
1401
+ logger.debug("resolveServePath", { servePath, hasOptional: !!optional, optionalKeys: optional ? Object.keys(optional) : [] });
1402
+ return servePath;
1403
+ }
1390
1404
  startStaticFileServer(managed) {
1391
1405
  try {
1392
1406
  const __filename4 = fileURLToPath2(import.meta.url);
1393
1407
  const __dirname4 = path.dirname(__filename4);
1394
1408
  const fileServerWorkerPath = path.join(__dirname4, "workers", "file_serve_worker.cjs");
1409
+ logger.info("Starting static file server worker", {
1410
+ dir: managed.serve,
1411
+ forwarding: JSON.stringify(managed.tunnelConfig?.forwarding),
1412
+ workerPath: fileServerWorkerPath
1413
+ });
1395
1414
  const staticServerWorker = new Worker(fileServerWorkerPath, {
1396
1415
  workerData: {
1397
1416
  dir: managed.serve,
1398
- port: managed.tunnelConfig?.forwarding
1417
+ forwarding: managed.tunnelConfig?.forwarding
1399
1418
  }
1400
1419
  });
1401
1420
  staticServerWorker.on("message", (msg) => {
1402
1421
  switch (msg.type) {
1403
1422
  case "started":
1404
- logger.info("Static file server started", { dir: managed.serve });
1423
+ logger.info("Static file server started", { dir: managed.serve, port: msg.portNum });
1405
1424
  break;
1406
1425
  case "warning":
1407
1426
  if (msg.code === "INVALID_TUNNEL_SERVE_PATH") {
@@ -2829,6 +2848,7 @@ export {
2829
2848
  TunnelWarningCode,
2830
2849
  TunnelOperations,
2831
2850
  RemoteManagementUnauthorizedError,
2851
+ buildRemoteManagementWsUrl,
2832
2852
  parseRemoteManagement,
2833
2853
  initiateRemoteManagement,
2834
2854
  closeRemoteManagement,