pinggy 0.4.4 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -589,15 +589,15 @@ interface TunnelResponseV2 {
589
589
  greetmsg?: string;
590
590
  }
591
591
  interface TunnelHandler {
592
- handleStart(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
593
- handleStartV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
594
- handleUpdateConfig(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
595
- handleUpdateConfigV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
592
+ handleStart(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
593
+ handleStartV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
594
+ handleUpdateConfig(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
595
+ handleUpdateConfigV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
596
596
  handleList(): Promise<TunnelResponse[] | ErrorResponse>;
597
597
  handleListV2(): Promise<TunnelResponseV2[] | ErrorResponse>;
598
598
  handleStop(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
599
599
  handleGet(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
600
- handleRestart(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
600
+ handleRestart(tunnelid: string, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
601
601
  handleRegisterStatsListener(tunnelid: string, listener: (tunnelId: string, stats: TunnelUsageType) => void): void;
602
602
  handleUnregisterStatsListener(tunnelid: string, listnerId: string): void;
603
603
  handleGetTunnelStats(tunnelid: string): TunnelUsageType[] | ErrorResponse;
@@ -609,18 +609,20 @@ declare class TunnelOperations implements TunnelHandler {
609
609
  private tunnelManager;
610
610
  constructor();
611
611
  private buildStatus;
612
+ private buildPendingTunnelResponse;
613
+ private buildPendingTunnelResponseV2;
612
614
  private buildTunnelResponse;
613
615
  private buildTunnelResponseV2;
614
616
  private error;
615
- handleStart(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
616
- handleStartV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
617
- handleUpdateConfig(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
618
- handleUpdateConfigV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
617
+ handleStart(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
618
+ handleStartV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
619
+ handleUpdateConfig(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
620
+ handleUpdateConfigV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
619
621
  handleListV2(): Promise<TunnelResponseV2[] | ErrorResponse>;
620
622
  handleList(): Promise<TunnelResponse[] | ErrorResponse>;
621
623
  handleStop(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
622
624
  handleGet(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
623
- handleRestart(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
625
+ handleRestart(tunnelid: string, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
624
626
  handleRegisterStatsListener(tunnelid: string, listener: (tunnelId: string, stats: TunnelUsageType) => void): void;
625
627
  handleUnregisterStatsListener(tunnelid: string, listnerId: string): void;
626
628
  handleGetTunnelStats(tunnelid: string): TunnelUsageType[] | ErrorResponse;
@@ -640,6 +642,9 @@ interface BaseLogConfig {
640
642
  type BaseLogConfigType = BaseLogConfig;
641
643
  declare function enablePackageLogging(opts?: BaseLogConfigType): winston.Logger;
642
644
 
645
+ declare class RemoteManagementUnauthorizedError extends Error {
646
+ constructor();
647
+ }
643
648
  /**
644
649
  * Initiate remote management mode with a WebSocket connection.
645
650
  * - Connect with Authorization: Bearer <token>
@@ -649,6 +654,10 @@ declare function enablePackageLogging(opts?: BaseLogConfigType): winston.Logger;
649
654
  */
650
655
  declare function initiateRemoteManagement(remoteManagementConfig: RemoteManagementConfig): Promise<RemoteManagementState>;
651
656
  declare function closeRemoteManagement(timeoutMs?: number): Promise<RemoteManagementState>;
657
+ /**
658
+ * Start remote management loop in background; returns after first connection attempt.
659
+ */
660
+ declare function startRemoteManagement(remoteManagementConfig: RemoteManagementConfig): Promise<RemoteManagementState>;
652
661
  declare function getRemoteManagementState(): RemoteManagementState;
653
662
 
654
- export { type AdditionalForwarding, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, type StartListener, type StatsListener, type Status, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, closeRemoteManagement, enablePackageLogging, getRemoteManagementState, initiateRemoteManagement };
663
+ export { type AdditionalForwarding, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, RemoteManagementUnauthorizedError, type StartListener, type StatsListener, type Status, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, closeRemoteManagement, enablePackageLogging, getRemoteManagementState, initiateRemoteManagement, startRemoteManagement };
package/dist/index.d.ts CHANGED
@@ -589,15 +589,15 @@ interface TunnelResponseV2 {
589
589
  greetmsg?: string;
590
590
  }
591
591
  interface TunnelHandler {
592
- handleStart(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
593
- handleStartV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
594
- handleUpdateConfig(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
595
- handleUpdateConfigV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
592
+ handleStart(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
593
+ handleStartV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
594
+ handleUpdateConfig(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
595
+ handleUpdateConfigV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
596
596
  handleList(): Promise<TunnelResponse[] | ErrorResponse>;
597
597
  handleListV2(): Promise<TunnelResponseV2[] | ErrorResponse>;
598
598
  handleStop(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
599
599
  handleGet(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
600
- handleRestart(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
600
+ handleRestart(tunnelid: string, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
601
601
  handleRegisterStatsListener(tunnelid: string, listener: (tunnelId: string, stats: TunnelUsageType) => void): void;
602
602
  handleUnregisterStatsListener(tunnelid: string, listnerId: string): void;
603
603
  handleGetTunnelStats(tunnelid: string): TunnelUsageType[] | ErrorResponse;
@@ -609,18 +609,20 @@ declare class TunnelOperations implements TunnelHandler {
609
609
  private tunnelManager;
610
610
  constructor();
611
611
  private buildStatus;
612
+ private buildPendingTunnelResponse;
613
+ private buildPendingTunnelResponseV2;
612
614
  private buildTunnelResponse;
613
615
  private buildTunnelResponseV2;
614
616
  private error;
615
- handleStart(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
616
- handleStartV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
617
- handleUpdateConfig(config: TunnelConfig): Promise<TunnelResponse | ErrorResponse>;
618
- handleUpdateConfigV2(config: TunnelConfigV1): Promise<TunnelResponseV2 | ErrorResponse>;
617
+ handleStart(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
618
+ handleStartV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
619
+ handleUpdateConfig(config: TunnelConfig, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
620
+ handleUpdateConfigV2(config: TunnelConfigV1, noWait?: boolean): Promise<TunnelResponseV2 | ErrorResponse>;
619
621
  handleListV2(): Promise<TunnelResponseV2[] | ErrorResponse>;
620
622
  handleList(): Promise<TunnelResponse[] | ErrorResponse>;
621
623
  handleStop(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
622
624
  handleGet(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
623
- handleRestart(tunnelid: string): Promise<TunnelResponse | ErrorResponse>;
625
+ handleRestart(tunnelid: string, noWait?: boolean): Promise<TunnelResponse | ErrorResponse>;
624
626
  handleRegisterStatsListener(tunnelid: string, listener: (tunnelId: string, stats: TunnelUsageType) => void): void;
625
627
  handleUnregisterStatsListener(tunnelid: string, listnerId: string): void;
626
628
  handleGetTunnelStats(tunnelid: string): TunnelUsageType[] | ErrorResponse;
@@ -640,6 +642,9 @@ interface BaseLogConfig {
640
642
  type BaseLogConfigType = BaseLogConfig;
641
643
  declare function enablePackageLogging(opts?: BaseLogConfigType): winston.Logger;
642
644
 
645
+ declare class RemoteManagementUnauthorizedError extends Error {
646
+ constructor();
647
+ }
643
648
  /**
644
649
  * Initiate remote management mode with a WebSocket connection.
645
650
  * - Connect with Authorization: Bearer <token>
@@ -649,6 +654,10 @@ declare function enablePackageLogging(opts?: BaseLogConfigType): winston.Logger;
649
654
  */
650
655
  declare function initiateRemoteManagement(remoteManagementConfig: RemoteManagementConfig): Promise<RemoteManagementState>;
651
656
  declare function closeRemoteManagement(timeoutMs?: number): Promise<RemoteManagementState>;
657
+ /**
658
+ * Start remote management loop in background; returns after first connection attempt.
659
+ */
660
+ declare function startRemoteManagement(remoteManagementConfig: RemoteManagementConfig): Promise<RemoteManagementState>;
652
661
  declare function getRemoteManagementState(): RemoteManagementState;
653
662
 
654
- export { type AdditionalForwarding, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, type StartListener, type StatsListener, type Status, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, closeRemoteManagement, enablePackageLogging, getRemoteManagementState, initiateRemoteManagement };
663
+ export { type AdditionalForwarding, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, RemoteManagementUnauthorizedError, type StartListener, type StatsListener, type Status, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, closeRemoteManagement, enablePackageLogging, getRemoteManagementState, initiateRemoteManagement, startRemoteManagement };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ RemoteManagementUnauthorizedError,
3
4
  TunnelErrorCodeType,
4
5
  TunnelManager,
5
6
  TunnelOperations,
@@ -8,11 +9,12 @@ import {
8
9
  closeRemoteManagement,
9
10
  getRemoteManagementState,
10
11
  initiateRemoteManagement,
11
- printer_default
12
- } from "./chunk-MBN3YBO4.js";
12
+ printer_default,
13
+ startRemoteManagement
14
+ } from "./chunk-STEISST3.js";
13
15
  import {
14
16
  enablePackageLogging
15
- } from "./chunk-HUN2MRZO.js";
17
+ } from "./chunk-3RTRUYNW.js";
16
18
 
17
19
  // src/utils/detect_vc_redist_on_windows.ts
18
20
  import fs from "fs";
@@ -104,13 +106,13 @@ async function verifyAndLoad() {
104
106
  process.exit(1);
105
107
  }
106
108
  }
107
- await import("./main-PFPDXIRG.js");
109
+ await import("./main-XKFFUSKJ.js");
108
110
  }
109
111
  verifyAndLoad().catch((err) => {
110
- printer_default.error(`Failed to start CLI:, ${err}`);
111
- process.exit(1);
112
+ printer_default.fatal(`Failed to start CLI:, ${err}`);
112
113
  });
113
114
  export {
115
+ RemoteManagementUnauthorizedError,
114
116
  TunnelErrorCodeType,
115
117
  TunnelManager,
116
118
  TunnelOperations,
@@ -119,5 +121,6 @@ export {
119
121
  closeRemoteManagement,
120
122
  enablePackageLogging,
121
123
  getRemoteManagementState,
122
- initiateRemoteManagement
124
+ initiateRemoteManagement,
125
+ startRemoteManagement
123
126
  };
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ RemoteManagementUnauthorizedError,
3
4
  TunnelManager,
4
5
  TunnelOperations,
5
6
  closeRemoteManagement,
@@ -10,12 +11,12 @@ import {
10
11
  isValidPort,
11
12
  parseRemoteManagement,
12
13
  printer_default
13
- } from "./chunk-MBN3YBO4.js";
14
+ } from "./chunk-STEISST3.js";
14
15
  import {
15
16
  configureLogger,
16
17
  enablePackageLogging,
17
18
  logger
18
- } from "./chunk-HUN2MRZO.js";
19
+ } from "./chunk-3RTRUYNW.js";
19
20
 
20
21
  // src/cli/options.ts
21
22
  var cliOptions = {
@@ -256,6 +257,19 @@ import fs from "fs";
256
257
  import path from "path";
257
258
  import { isIP as isIP2 } from "net";
258
259
  var domainRegex = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
260
+ function removeIPv6Brackets(ip) {
261
+ if (ip.startsWith("[") && ip.endsWith("]")) {
262
+ return ip.slice(1, -1);
263
+ }
264
+ return ip;
265
+ }
266
+ function isValidServerAddress(host) {
267
+ const normalized = removeIPv6Brackets(host.trim());
268
+ if (!normalized) {
269
+ return false;
270
+ }
271
+ return domainRegex.test(normalized) || isIP2(normalized) !== 0;
272
+ }
259
273
  var KEYWORDS = /* @__PURE__ */ new Set([
260
274
  TunnelType.Http,
261
275
  TunnelType.Tcp,
@@ -274,10 +288,12 @@ function parseUserAndDomain(str) {
274
288
  let server;
275
289
  let qrCode;
276
290
  let forceFlag;
277
- if (!str) return { token, type, server, qrCode, forceFlag };
291
+ if (!str) {
292
+ return { token, type, server, qrCode, forceFlag };
293
+ }
278
294
  if (str.includes("@")) {
279
295
  const [user, domain] = str.split("@", 2);
280
- if (domainRegex.test(domain)) {
296
+ if (isValidServerAddress(domain)) {
281
297
  let processKeyword2 = function(keyword) {
282
298
  if ([TunnelType.Http, TunnelType.Tcp, TunnelType.Tls, TunnelType.Udp, TunnelType.TlsTcp].includes(keyword)) {
283
299
  type = keyword;
@@ -313,7 +329,7 @@ function parseUserAndDomain(str) {
313
329
  }
314
330
  }
315
331
  }
316
- } else if (domainRegex.test(str)) {
332
+ } else if (isValidServerAddress(str)) {
317
333
  server = str;
318
334
  }
319
335
  return { token, type, server, qrCode, forceFlag };
@@ -327,21 +343,39 @@ function parseUsers(positionalArgs, explicitToken) {
327
343
  let remaining = [...positionalArgs];
328
344
  if (typeof explicitToken === "string") {
329
345
  const parsed = parseUserAndDomain(explicitToken);
330
- if (parsed.server) server = parsed.server;
331
- if (parsed.type) type = parsed.type;
332
- if (parsed.token) token = parsed.token;
333
- if (parsed.forceFlag) forceFlag = true;
334
- if (parsed.qrCode) qrCode = true;
346
+ if (parsed.server) {
347
+ server = parsed.server;
348
+ }
349
+ if (parsed.type) {
350
+ type = parsed.type;
351
+ }
352
+ if (parsed.token) {
353
+ token = parsed.token;
354
+ }
355
+ if (parsed.forceFlag) {
356
+ forceFlag = true;
357
+ }
358
+ if (parsed.qrCode) {
359
+ qrCode = true;
360
+ }
335
361
  }
336
362
  if (remaining.length > 0) {
337
363
  const first = remaining[0];
338
364
  const parsed = parseUserAndDomain(first);
339
365
  if (parsed.server) {
340
366
  server = parsed.server;
341
- if (parsed.type) type = parsed.type;
342
- if (parsed.token) token = parsed.token;
343
- if (parsed.forceFlag) forceFlag = true;
344
- if (parsed.qrCode) qrCode = true;
367
+ if (parsed.type) {
368
+ type = parsed.type;
369
+ }
370
+ if (parsed.token) {
371
+ token = parsed.token;
372
+ }
373
+ if (parsed.forceFlag) {
374
+ forceFlag = true;
375
+ }
376
+ if (parsed.qrCode) {
377
+ qrCode = true;
378
+ }
345
379
  remaining = remaining.slice(1);
346
380
  }
347
381
  }
@@ -354,7 +388,9 @@ function parseType(finalConfig, values, inferredType) {
354
388
  }
355
389
  }
356
390
  function parseLocalPort(finalConfig, values) {
357
- if (typeof values.localport !== "string") return null;
391
+ if (typeof values.localport !== "string") {
392
+ return null;
393
+ }
358
394
  let lp = values.localport.trim();
359
395
  let isHttps = false;
360
396
  if (lp.startsWith("https://")) {
@@ -384,15 +420,11 @@ function parseLocalPort(finalConfig, values) {
384
420
  }
385
421
  return null;
386
422
  }
387
- function removeIPv6Brackets(ip) {
388
- if (ip.startsWith("[") && ip.endsWith("]")) {
389
- return ip.slice(1, -1);
390
- }
391
- return ip;
392
- }
393
423
  function isValidHostAddress(host) {
394
424
  const normalized = removeIPv6Brackets(host.trim());
395
- if (normalized.length === 0) return false;
425
+ if (normalized.length === 0) {
426
+ return false;
427
+ }
396
428
  return normalized === "localhost" || isIP2(normalized) !== 0;
397
429
  }
398
430
  function ipv6SafeSplitColon(s) {
@@ -416,7 +448,7 @@ function ipv6SafeSplitColon(s) {
416
448
  result.push(buf);
417
449
  return result;
418
450
  }
419
- var VALID_PROTOCOLS = ["http", "tcp", "udp", "tls"];
451
+ var VALID_PROTOCOLS = [TunnelType.Http, TunnelType.Tcp, TunnelType.Udp, TunnelType.Tls, TunnelType.TlsTcp];
420
452
  function parseDefaultForwarding(forwarding) {
421
453
  const parts = ipv6SafeSplitColon(forwarding);
422
454
  if (parts.length === 3) {
@@ -436,7 +468,9 @@ function parseDefaultForwarding(forwarding) {
436
468
  }
437
469
  function parseAdditionalForwarding(forwarding) {
438
470
  const toPort = (v) => {
439
- if (!v) return null;
471
+ if (!v) {
472
+ return null;
473
+ }
440
474
  const n = parseInt(v, 10);
441
475
  return Number.isNaN(n) ? null : n;
442
476
  };
@@ -448,7 +482,7 @@ function parseAdditionalForwarding(forwarding) {
448
482
  }
449
483
  const firstPart = parsed[0];
450
484
  const [hostPart] = firstPart.split("@");
451
- let protocol = "http";
485
+ let protocol = TunnelType.Http;
452
486
  let remoteDomainRaw;
453
487
  let remotePort = 0;
454
488
  if (hostPart.includes("//")) {
@@ -462,7 +496,7 @@ function parseAdditionalForwarding(forwarding) {
462
496
  return new Error("invalid forwarding address format");
463
497
  }
464
498
  remoteDomainRaw = domainAndPort[0];
465
- if (!remoteDomainRaw || !domainRegex.test(remoteDomainRaw)) {
499
+ if (!remoteDomainRaw || !isValidServerAddress(remoteDomainRaw)) {
466
500
  return new Error("invalid remote domain");
467
501
  }
468
502
  const parsedRemotePort = toPort(domainAndPort[1]);
@@ -478,10 +512,10 @@ function parseAdditionalForwarding(forwarding) {
478
512
  }
479
513
  } else {
480
514
  remoteDomainRaw = hostPart;
481
- if (!domainRegex.test(remoteDomainRaw)) {
515
+ if (!isValidServerAddress(remoteDomainRaw)) {
482
516
  return new Error("invalid remote domain");
483
517
  }
484
- protocol = "http";
518
+ protocol = TunnelType.Http;
485
519
  remotePort = 0;
486
520
  }
487
521
  const localDomain = removeIPv6Brackets(parsed[2] || "localhost");
@@ -515,7 +549,9 @@ function parseReverseTunnelAddr(finalConfig, values, primaryType) {
515
549
  });
516
550
  } else if (slicedForwarding.length === 4) {
517
551
  const parsed = parseAdditionalForwarding(forwarding);
518
- if (parsed instanceof Error) return parsed;
552
+ if (parsed instanceof Error) {
553
+ return parsed;
554
+ }
519
555
  forwardingData.push(parsed);
520
556
  } else {
521
557
  return new Error(
@@ -527,7 +563,9 @@ function parseReverseTunnelAddr(finalConfig, values, primaryType) {
527
563
  return null;
528
564
  }
529
565
  function parseLocalTunnelAddr(finalConfig, values) {
530
- if (!Array.isArray(values.L) || values.L.length === 0) return null;
566
+ if (!Array.isArray(values.L) || values.L.length === 0) {
567
+ return null;
568
+ }
531
569
  const firstL = values.L[0];
532
570
  const parts = ipv6SafeSplitColon(firstL);
533
571
  let debuggerHost = "localhost";
@@ -551,7 +589,9 @@ function parseLocalTunnelAddr(finalConfig, values) {
551
589
  }
552
590
  function parseDebugger(finalConfig, values) {
553
591
  let dbg = values.debugger;
554
- if (typeof dbg !== "string") return;
592
+ if (typeof dbg !== "string") {
593
+ return;
594
+ }
555
595
  dbg = dbg.startsWith(":") ? dbg.slice(1) : dbg;
556
596
  const d = parseInt(dbg, 10);
557
597
  if (!Number.isNaN(d) && isValidPort(d)) {
@@ -610,7 +650,9 @@ function isSaveConfOption(values) {
610
650
  }
611
651
  function parseServe(finalConfig, values) {
612
652
  const sv = values.serve;
613
- if (typeof sv !== "string" || sv.trim().length === 0) return null;
653
+ if (typeof sv !== "string" || sv.trim().length === 0) {
654
+ return null;
655
+ }
614
656
  finalConfig.optional.serve = sv;
615
657
  return null;
616
658
  }
@@ -651,7 +693,7 @@ async function buildFinalConfig(values, positionals) {
651
693
  // Apply loaded config on top of defaults
652
694
  configId: getRandomId(),
653
695
  token: token || (configFromFile?.token || (typeof values.token === "string" ? values.token : "")),
654
- serverAddress: server || (configFromFile?.serverAddress || defaultOptions.serverAddress),
696
+ serverAddress: server ? removeIPv6Brackets(server) : configFromFile?.serverAddress || defaultOptions.serverAddress,
655
697
  isQRCode: qrCode || (configFromFile?.isQRCode || false),
656
698
  autoReconnect: configFromFile?.autoReconnect ? configFromFile.autoReconnect : defaultOptions.autoReconnect,
657
699
  optional: {
@@ -662,18 +704,32 @@ async function buildFinalConfig(values, positionals) {
662
704
  type = parseType(finalConfig, values, type);
663
705
  parseToken(finalConfig, token || values.token);
664
706
  const dbgErr = parseDebugger(finalConfig, values);
665
- if (dbgErr instanceof Error) throw dbgErr;
707
+ if (dbgErr instanceof Error) {
708
+ throw dbgErr;
709
+ }
666
710
  const lpErr = parseLocalPort(finalConfig, values);
667
- if (lpErr instanceof Error) throw lpErr;
711
+ if (lpErr instanceof Error) {
712
+ throw lpErr;
713
+ }
668
714
  const rErr = parseReverseTunnelAddr(finalConfig, values, type);
669
- if (rErr instanceof Error) throw rErr;
715
+ if (rErr instanceof Error) {
716
+ throw rErr;
717
+ }
670
718
  const lErr = parseLocalTunnelAddr(finalConfig, values);
671
- if (lErr instanceof Error) throw lErr;
719
+ if (lErr instanceof Error) {
720
+ throw lErr;
721
+ }
672
722
  const serveErr = parseServe(finalConfig, values);
673
- if (serveErr instanceof Error) throw serveErr;
723
+ if (serveErr instanceof Error) {
724
+ throw serveErr;
725
+ }
674
726
  const autoReconnectErr = parseAutoReconnect(finalConfig, values);
675
- if (autoReconnectErr instanceof Error) throw autoReconnectErr;
676
- if (forceFlag || values.force) finalConfig.force = true;
727
+ if (autoReconnectErr instanceof Error) {
728
+ throw autoReconnectErr;
729
+ }
730
+ if (forceFlag || values.force) {
731
+ finalConfig.force = true;
732
+ }
677
733
  parseArgs(finalConfig, remainingPositionals);
678
734
  storeJson(finalConfig, saveconf);
679
735
  return finalConfig;
@@ -686,15 +742,26 @@ function isAttachedReverseOrLocalFlag(arg) {
686
742
  return /^-[RL].+/.test(arg);
687
743
  }
688
744
  function shouldMergeReverseOrLocalFragment(current, next) {
689
- if (next.startsWith("-")) return false;
690
- if (next.startsWith(".")) return true;
745
+ if (next.startsWith("-")) {
746
+ return false;
747
+ }
748
+ if (next.startsWith(".")) {
749
+ return true;
750
+ }
691
751
  const body = current.slice(2);
692
- if (body.endsWith(":")) return true;
693
- if (body.includes("//") && !body.includes(":")) return true;
752
+ if (body.endsWith(":")) {
753
+ return true;
754
+ }
755
+ if (body.includes("//") && !body.includes(":")) {
756
+ return true;
757
+ }
694
758
  return false;
695
759
  }
696
760
  function preprocessWindowsArgs(args) {
697
- if (os.platform() !== "win32") return args;
761
+ if (os.platform() !== "win32") {
762
+ return args;
763
+ }
764
+ ;
698
765
  const out = [];
699
766
  let i = 0;
700
767
  while (i < args.length) {
@@ -772,13 +839,12 @@ import QRCode from "qrcode";
772
839
  async function createQrCodes(urls) {
773
840
  const codes = [];
774
841
  for (const url of urls) {
775
- const qr = await QRCode.toString(url, {
776
- type: "terminal",
777
- small: true,
778
- margin: 0,
842
+ const raw = await QRCode.toString(url, {
843
+ type: "utf8",
844
+ margin: 2,
779
845
  errorCorrectionLevel: "L"
780
846
  });
781
- codes.push(qr);
847
+ codes.push(raw);
782
848
  }
783
849
  return codes;
784
850
  }
@@ -790,6 +856,7 @@ import WebSocket from "ws";
790
856
  var defaultTuiConfig = {
791
857
  maxRequestPairs: 100,
792
858
  visibleRequestCount: 10,
859
+ visibleUrlCount: 7,
793
860
  viewportScrollMargin: 2,
794
861
  inactivityHttpSelectorTimeoutMs: 1e4
795
862
  };
@@ -797,6 +864,7 @@ function getTuiConfig() {
797
864
  return {
798
865
  maxRequestPairs: defaultTuiConfig.maxRequestPairs,
799
866
  visibleRequestCount: defaultTuiConfig.visibleRequestCount,
867
+ visibleUrlCount: defaultTuiConfig.visibleUrlCount,
800
868
  viewportScrollMargin: defaultTuiConfig.viewportScrollMargin,
801
869
  inactivityHttpSelectorTimeoutMs: defaultTuiConfig.inactivityHttpSelectorTimeoutMs
802
870
  };
@@ -1024,7 +1092,7 @@ function createFullUI(screen, urls, greet, tunnelConfig) {
1024
1092
  width: "100%-2",
1025
1093
  height: `100%-${lowerSectionTop + 6}`
1026
1094
  });
1027
- const isQrCodeRequested = tunnelConfig?.qrCode || false;
1095
+ const isQrCodeRequested = tunnelConfig?.isQRCode || false;
1028
1096
  const requestsBox = blessed.box({
1029
1097
  parent: lowerSection,
1030
1098
  top: 0,
@@ -1167,8 +1235,24 @@ function getBytesInt(b) {
1167
1235
  // src/tui/blessed/components/DisplayUpdaters.ts
1168
1236
  function updateUrlsDisplay(urlsBox, screen, urls, currentQrIndex) {
1169
1237
  if (!urlsBox) return;
1170
- let content = "{green-fg}{bold}Public URLs{/bold}{/green-fg}\n";
1171
- urls.forEach((url, index) => {
1238
+ const config = getTuiConfig();
1239
+ const { visibleUrlCount } = config;
1240
+ let viewportStart = 0;
1241
+ if (urls.length > visibleUrlCount) {
1242
+ viewportStart = Math.max(0, Math.min(
1243
+ currentQrIndex - Math.floor(visibleUrlCount / 2),
1244
+ urls.length - visibleUrlCount
1245
+ ));
1246
+ }
1247
+ const viewportEnd = Math.min(viewportStart + visibleUrlCount, urls.length);
1248
+ const visibleUrls = urls.slice(viewportStart, viewportEnd);
1249
+ let content = "{green-fg}{bold}Public URLs{/bold}{/green-fg}";
1250
+ if (viewportStart > 0) {
1251
+ content += ` {gray-fg}\u2191 ${viewportStart} more{/gray-fg}`;
1252
+ }
1253
+ content += "\n";
1254
+ visibleUrls.forEach((url, i) => {
1255
+ const index = viewportStart + i;
1172
1256
  const isSelected = index === currentQrIndex;
1173
1257
  const prefix = isSelected ? "\u2192 " : "\u2022 ";
1174
1258
  const color = isSelected ? "yellow" : "magenta";
@@ -1180,6 +1264,11 @@ function updateUrlsDisplay(urlsBox, screen, urls, currentQrIndex) {
1180
1264
  `;
1181
1265
  }
1182
1266
  });
1267
+ const itemsBelow = urls.length - viewportEnd;
1268
+ if (itemsBelow > 0) {
1269
+ content += `{gray-fg}\u2193 ${itemsBelow} more{/gray-fg}
1270
+ `;
1271
+ }
1183
1272
  urlsBox.setContent(content);
1184
1273
  screen.render();
1185
1274
  }
@@ -1847,7 +1936,7 @@ var TunnelTui = class {
1847
1936
  }
1848
1937
  }
1849
1938
  async generateQrCodes() {
1850
- if (this.tunnelConfig?.qrCode && this.urls.length > 0) {
1939
+ if (this.tunnelConfig?.isQRCode && this.urls.length > 0) {
1851
1940
  this.qrCodes = await createQrCodes(this.urls);
1852
1941
  this.updateQrCodeDisplay();
1853
1942
  }
@@ -2080,7 +2169,7 @@ async function startCli(finalConfig, manager) {
2080
2169
  });
2081
2170
  }
2082
2171
  manager2.registerWorkerErrorListner(tunnel.tunnelid, (_tunnelid, error) => {
2083
- printer_default.error(`${error.message}`);
2172
+ printer_default.fatal(`${error.message}`);
2084
2173
  });
2085
2174
  await manager2.startTunnel(tunnel.tunnelid);
2086
2175
  printer_default.stopSpinnerSuccess(" Connected to Pinggy");
@@ -2205,7 +2294,7 @@ async function startCli(finalConfig, manager) {
2205
2294
  }
2206
2295
  } catch (err) {
2207
2296
  printer_default.stopSpinnerFail("Failed to connect");
2208
- printer_default.error(err.message || "Unknown error");
2297
+ printer_default.fatal(err.message || "Unknown error");
2209
2298
  throw err;
2210
2299
  }
2211
2300
  }
@@ -2236,9 +2325,8 @@ async function main() {
2236
2325
  }
2237
2326
  const parseResult = await parseRemoteManagement(values);
2238
2327
  if (parseResult?.ok === false) {
2239
- printer_default.error(parseResult.error);
2240
2328
  logger.error("Failed to initiate remote management:", parseResult.error);
2241
- process.exit(1);
2329
+ printer_default.fatal(parseResult.error);
2242
2330
  }
2243
2331
  logger.debug("Building final config from CLI values and positionals", { values, positionals });
2244
2332
  const finalConfig = await buildFinalConfig(values, positionals);
@@ -2246,7 +2334,7 @@ async function main() {
2246
2334
  await startCli(finalConfig, manager);
2247
2335
  } catch (error) {
2248
2336
  logger.error("Unhandled error in CLI:", error);
2249
- printer_default.error(error);
2337
+ printer_default.fatal(error);
2250
2338
  }
2251
2339
  }
2252
2340
  var currentFile = fileURLToPath(import.meta.url);
@@ -2260,6 +2348,7 @@ if (entryFile && entryFile === currentFile) {
2260
2348
  main();
2261
2349
  }
2262
2350
  export {
2351
+ RemoteManagementUnauthorizedError,
2263
2352
  TunnelManager,
2264
2353
  TunnelOperations,
2265
2354
  closeRemoteManagement,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "../chunk-HUN2MRZO.js";
3
+ } from "../chunk-3RTRUYNW.js";
4
4
 
5
5
  // src/workers/file_serve_worker.ts
6
6
  import { parentPort, workerData } from "worker_threads";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinggy",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "description": "Create secure, shareable tunnels to your localhost and manage them from the command line. ",
@@ -51,7 +51,7 @@
51
51
  ]
52
52
  },
53
53
  "dependencies": {
54
- "@pinggy/pinggy": "^0.4.2",
54
+ "@pinggy/pinggy": "^0.4.3",
55
55
  "blessed": "^0.1.81",
56
56
  "clipboardy": "^5.0.0",
57
57
  "mime": "^4.1.0",
@@ -65,6 +65,7 @@
65
65
  "@types/blessed": "^0.1.25",
66
66
  "@types/jest": "^30.0.0",
67
67
  "@types/node": "^24.3.0",
68
+ "@types/qrcode": "^1.5.6",
68
69
  "@types/qrcode-terminal": "^0.12.2",
69
70
  "@types/ws": "^8.18.1",
70
71
  "@yao-pkg/pkg": "^6.11.0",