Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/improsocial/impro
An extensible Bluesky client for web impro.social
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111import { spawn, spawnSync } from "node:child_process";import { rmSync } from "node:fs";
const LOCAL_PORT = 8080;const TUNNEL_URL_PATTERN = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/;
function isCloudflaredInstalled() { const result = spawnSync("cloudflared", ["--version"], { stdio: "ignore" }); return !result.error && result.status === 0;}
function startCloudflared() { return spawn( "cloudflared", ["tunnel", "--url", `http://localhost:${LOCAL_PORT}`, "--no-autoupdate"], { stdio: ["ignore", "pipe", "pipe"] }, );}
function waitForTunnelUrl(cloudflared) { return new Promise((resolve, reject) => { let buffer = ""; let resolved = false;
const onData = (chunk) => { const text = chunk.toString(); if (resolved) return; buffer += text; const match = buffer.match(TUNNEL_URL_PATTERN); if (match) { resolved = true; cloudflared.stderr.off("data", onData); cloudflared.stdout.off("data", onData); resolve(match[0]); } };
cloudflared.stderr.on("data", onData); cloudflared.stdout.on("data", onData); cloudflared.on("exit", (code) => { if (!resolved) { reject( new Error( `cloudflared exited before printing a tunnel URL (code ${code})`, ), ); } }); });}
function startEleventy(hostName) { rmSync("build", { recursive: true, force: true }); const env = { ...process.env, NODE_ENV: "development" }; if (hostName) env.HOST_NAME = hostName; return spawn("npx", ["@11ty/eleventy", "--serve"], { stdio: "inherit", env, });}
async function startTunnel() { if (!isCloudflaredInstalled()) { console.error( "cloudflared not found. Install it to run the dev tunnel:\n" + " macOS: brew install cloudflared\n" + " Other: https://github.com/cloudflare/cloudflared/releases\n", ); process.exit(1); }
console.info("Starting cloudflared tunnel..."); const cloudflared = startCloudflared(); const tunnelUrl = await waitForTunnelUrl(cloudflared); const hostName = tunnelUrl.replace(/^https:\/\//, "");
console.info( "\n============================================================", ); console.info(`Tunnel ready: ${tunnelUrl}`); console.info( "============================================================\n", );
return { cloudflared, hostName };}
async function main() { const { cloudflared, hostName } = await startTunnel(); const eleventy = startEleventy(hostName);
let shuttingDown = false; const shutdown = (code) => { if (shuttingDown) return; shuttingDown = true; if (!cloudflared.killed) cloudflared.kill("SIGTERM"); if (!eleventy.killed) eleventy.kill("SIGTERM"); process.exit(code ?? 0); };
process.on("SIGINT", () => shutdown(0)); process.on("SIGTERM", () => shutdown(0)); cloudflared.on("exit", (code) => shutdown(code ?? 0)); eleventy.on("exit", (code) => shutdown(code ?? 0));}
main().catch((error) => { console.error(error); process.exit(1);});