mirror of
https://github.com/temetro/temetro.git
synced 2026-07-26 11:58:14 +00:00
a68b7f2573
Two changes so off-network wallet scanning actually works: - Force the cloudflared edge connection over http2 (TCP/443) instead of QUIC (UDP/7844) in both the Docker tunnel and the dev-tunnel script. QUIC is blocked on many networks/Docker setups, which left the tunnel stuck "Failed to dial a quic connection" and the QR pointing at a dead URL — the root cause of "must be on the same network" failures. - Gate the discovered quick-tunnel URL on real end-to-end reachability: poll the tunnel's own /health until it answers (Cloudflare 1033 clears in ~30s) before publishing it, and have /pair await that discovery so the QR never carries a not-yet-live URL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
87 lines
2.8 KiB
JavaScript
87 lines
2.8 KiB
JavaScript
// Run the backend with a public Cloudflare tunnel so a patient's phone can reach
|
|
// the wallet relay from ANY network (cellular, other Wi-Fi) — not just the LAN.
|
|
//
|
|
// npm run dev:tunnel
|
|
//
|
|
// It opens `cloudflared tunnel --url http://localhost:4000`, grabs the public
|
|
// https://<sub>.trycloudflare.com URL, and starts the backend with
|
|
// PUBLIC_RELAY_URL set to it — so the QR in "Import from a patient app" carries
|
|
// that public URL (over wss://). Requires cloudflared: `brew install cloudflared`.
|
|
|
|
import { spawn, spawnSync } from "node:child_process";
|
|
|
|
const PORT = process.env.PORT || "4000";
|
|
|
|
function hasCloudflared() {
|
|
const probe = spawnSync("cloudflared", ["--version"], { stdio: "ignore" });
|
|
return !probe.error;
|
|
}
|
|
|
|
if (!hasCloudflared()) {
|
|
console.error(
|
|
"\n✖ cloudflared is not installed.\n" +
|
|
" Install it, then re-run `npm run dev:tunnel`:\n\n" +
|
|
" brew install cloudflared # macOS\n" +
|
|
" # or see https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/\n",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
let backend = null;
|
|
let resolvedUrl = null;
|
|
const TUNNEL_RE = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/i;
|
|
|
|
console.log(`\n⛅ Starting Cloudflare tunnel to http://localhost:${PORT} …\n`);
|
|
|
|
const tunnel = spawn(
|
|
"cloudflared",
|
|
// --protocol http2 keeps the edge connection on TCP/443 (QUIC/UDP is blocked
|
|
// on many networks and would leave the tunnel unable to connect).
|
|
["tunnel", "--no-autoupdate", "--protocol", "http2", "--url", `http://localhost:${PORT}`],
|
|
{ stdio: ["ignore", "pipe", "pipe"] },
|
|
);
|
|
|
|
function onTunnelOutput(buf) {
|
|
const text = buf.toString();
|
|
process.stderr.write(text); // keep cloudflared's own logs visible
|
|
if (resolvedUrl) return;
|
|
const match = text.match(TUNNEL_RE);
|
|
if (match) {
|
|
resolvedUrl = match[0];
|
|
startBackend(resolvedUrl);
|
|
}
|
|
}
|
|
|
|
tunnel.stdout.on("data", onTunnelOutput);
|
|
tunnel.stderr.on("data", onTunnelOutput);
|
|
|
|
function startBackend(publicUrl) {
|
|
console.log(
|
|
`\n✅ Public relay URL: ${publicUrl}\n` +
|
|
" Generate a QR in the web app (Patients → Import from a patient app → QR);\n" +
|
|
" it will carry this URL, so a phone on any network can scan to connect.\n",
|
|
);
|
|
backend = spawn("npm", ["run", "dev"], {
|
|
stdio: "inherit",
|
|
env: { ...process.env, PUBLIC_RELAY_URL: publicUrl },
|
|
});
|
|
backend.on("exit", (code) => shutdown(code ?? 0));
|
|
}
|
|
|
|
function shutdown(code) {
|
|
for (const proc of [backend, tunnel]) {
|
|
if (proc && !proc.killed) proc.kill("SIGTERM");
|
|
}
|
|
process.exit(code);
|
|
}
|
|
|
|
tunnel.on("exit", (code) => {
|
|
if (!resolvedUrl) {
|
|
console.error("\n✖ cloudflared exited before a tunnel URL was established.");
|
|
}
|
|
shutdown(code ?? 0);
|
|
});
|
|
|
|
process.on("SIGINT", () => shutdown(0));
|
|
process.on("SIGTERM", () => shutdown(0));
|