uplink-cli 0.1.21 → 0.1.23

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.
@@ -3,6 +3,19 @@ import { join } from "path";
3
3
  import { apiRequest } from "../../http";
4
4
 
5
5
  export async function createAndStartTunnel(port: number): Promise<string> {
6
+ // Check if tunnel already running on this port
7
+ const existing = findTunnelClients().filter(c => c.port === port);
8
+ if (existing.length > 0) {
9
+ return [
10
+ `⚠ Tunnel already running on port ${port}`,
11
+ ``,
12
+ `→ PID: ${existing[0].pid}`,
13
+ `→ Token: ${existing[0].token.substring(0, 8)}...`,
14
+ ``,
15
+ `Use "Stop Tunnel" first to disconnect the existing tunnel.`,
16
+ ].join("\n");
17
+ }
18
+
6
19
  const result = await apiRequest("POST", "/v1/tunnels", { port });
7
20
  const url = result.url || "(no url)";
8
21
  const token = result.token || "(no token)";
@@ -609,7 +609,12 @@ export const menuCommand = new Command("menu")
609
609
  try { process.stdin.setRawMode(false); } catch { /* ignore */ }
610
610
  const activePorts = await scanCommonPorts();
611
611
 
612
- if (activePorts.length === 0) {
612
+ // Filter out ports that already have tunnels running
613
+ const runningTunnels = findTunnelClients();
614
+ const portsWithTunnels = new Set(runningTunnels.map(t => t.port));
615
+ const availablePorts = activePorts.filter(p => !portsWithTunnels.has(p));
616
+
617
+ if (availablePorts.length === 0) {
613
618
  // No ports found - show selector with just custom option and back
614
619
  const options: SelectOption[] = [
615
620
  { label: "Enter custom port", value: "custom" },
@@ -631,11 +636,17 @@ export const menuCommand = new Command("menu")
631
636
  return await createAndStartTunnel(port);
632
637
  }
633
638
 
634
- // Build options from found ports
635
- const options: SelectOption[] = activePorts.map((port) => ({
639
+ // Build options from found ports (excluding those with running tunnels)
640
+ const options: SelectOption[] = availablePorts.map((port) => ({
636
641
  label: `Port ${port}`,
637
642
  value: port,
638
643
  }));
644
+ // Show ports with running tunnels as info
645
+ if (portsWithTunnels.size > 0) {
646
+ for (const port of portsWithTunnels) {
647
+ options.push({ label: `Port ${port} (tunnel running)`, value: `skip-${port}` });
648
+ }
649
+ }
639
650
  options.push({ label: "Enter custom port", value: "custom" });
640
651
 
641
652
  const result = await inlineSelect("Select port to expose", options, true);
@@ -652,6 +663,10 @@ export const menuCommand = new Command("menu")
652
663
  try { process.stdin.setRawMode(false); } catch { /* ignore */ }
653
664
  const answer = await promptLine("Enter port number (default 3000): ");
654
665
  port = Number(answer) || 3000;
666
+ } else if (typeof result.value === "string" && result.value.startsWith("skip-")) {
667
+ // Port with running tunnel selected - show info message
668
+ restoreRawMode();
669
+ return `⚠ Port ${result.value.replace("skip-", "")} already has a tunnel running.\nUse "Stop Tunnel" first to disconnect it.`;
655
670
  } else {
656
671
  port = result.value as number;
657
672
  }
@@ -1339,6 +1354,19 @@ export const menuCommand = new Command("menu")
1339
1354
  });
1340
1355
 
1341
1356
  async function createAndStartTunnel(port: number): Promise<string> {
1357
+ // Check if tunnel already running on this port
1358
+ const existing = findTunnelClients().filter(c => c.port === port);
1359
+ if (existing.length > 0) {
1360
+ return [
1361
+ `⚠ Tunnel already running on port ${port}`,
1362
+ ``,
1363
+ `→ PID: ${existing[0].pid}`,
1364
+ `→ Token: ${existing[0].token.substring(0, 8)}...`,
1365
+ ``,
1366
+ `Use "Stop Tunnel" first to disconnect the existing tunnel.`,
1367
+ ].join("\n");
1368
+ }
1369
+
1342
1370
  // Create tunnel
1343
1371
  const result = await apiRequest("POST", "/v1/tunnels", { port });
1344
1372
  const url = result.url || "(no url)";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uplink-cli",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "Expose localhost to the internet in seconds. Interactive terminal UI, permanent custom domains, zero config. A modern ngrok alternative.",
5
5
  "keywords": [
6
6
  "tunnel",