@frames.js/debugger
Version:
Debug your Frames.js applications
150 lines (132 loc) • 4.45 kB
JavaScript
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { createServer } from "http";
import { parse } from "url";
import next from "next";
import isPortReachable from "is-port-reachable";
import path from "node:path";
import { fileURLToPath } from "node:url";
import open from "open";
const args = yargs(hideBin(process.argv))
.usage("Usage: $0 [args]")
.option("farcaster-developer-mnemonic", {
alias: "fdm",
type: "string",
description:
"Needed for the debugger to create a real Farcaster signer. Get this by exporting your seed phrase from the Warpcast app. Don't share that seed phrase with anyone.",
default: process.env.FARCASTER_DEVELOPER_MNEMONIC,
})
.option("farcaster-developer-fid", {
alias: "fid",
type: "number",
description: `Only needed for the debugger to create a real Farcaster signer. Get this by visiting your Warpcast profile, pressing the kebab (three dots) menu and then "About" and then your fid should be there.`,
default:
process.env.FARCASTER_DEVELOPER_ID || process.env.FARCASTER_DEVELOPER_FID,
})
.option("kv-rest-api-url", {
alias: "kvurl",
type: "string",
description:
"Sets debugger to store Farcaster Frames v2 events into redis instead of SQLite",
default: process.env.KV_REST_API_URL,
})
.option("kv-rest-api-token", {
alias: "kvtoken",
type: "string",
description:
"Sets debugger to store Farcaster Frames v2 events into redis instead of SQLite",
default: process.env.KV_REST_API_TOKEN,
})
.option("signer-url", {
type: "string",
description:
"URL of the signer to use to create a signer. If value is not provided and no farcaster-developer-id and farcaster-developer-mnemonic is provided it uses https://debugger.framesjs.org/signer.",
default: process.env.SIGNER_URL,
})
.option("port", {
alias: "p",
type: "number",
description: "Port to run the debugger on. Default is 3010.",
default: 3010,
})
.option("url", {
alias: "u",
type: "string",
description: "Frame to debug",
default: process.env.NEXT_PUBLIC_HOST,
}).argv;
if (args["farcaster-developer-mnemonic"]) {
process.env.FARCASTER_DEVELOPER_MNEMONIC =
args["farcaster-developer-mnemonic"];
}
if (args["farcaster-developer-fid"]) {
process.env.FARCASTER_DEVELOPER_ID = args["farcaster-developer-fid"];
}
if (args["kv-rest-api-url"]) {
process.env.KV_REST_API_URL = args["kv-rest-api-url"];
}
if (args["kv-rest-api-token"]) {
process.env.KV_REST_API_TOKEN = args["kv-rest-api-token"];
}
if (args["signer-url"]) {
process.env.SIGNER_URL = args["signer-url"];
}
const dev = false;
const hostname = "localhost";
/**
* @param {Number} min
* @param {Number} max
* @returns Number
*/
function getRandomInt(min, max) {
const minCeiled = Math.ceil(min);
const maxFloored = Math.floor(max);
return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled);
}
/**
* @param {Number} port
* @returns Promise<Number>
*/
async function resolveAvailablePort(port) {
const isReachable = await isPortReachable(port, { host: hostname });
if (isReachable) {
return resolveAvailablePort(getRandomInt(3000, 50000));
}
return port;
}
const port = await resolveAvailablePort(args.port);
const app = next({
dev,
hostname,
port,
// resolve dirname relative to current file as we can call the command from any directory in the system
dir: path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../"),
});
const handle = app.getRequestHandler();
const url = `http://${hostname}:${port}`;
const initialUrl = `${url}${args.url ? `?url=${args.url}` : ""}`;
const hubUrl = `${url}/hub`;
await app.prepare();
createServer(async (req, res) => {
try {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true);
await handle(req, res, parsedUrl);
} catch (err) {
console.error("Error occurred handling", req.url, err);
res.statusCode = 500;
res.end("internal server error");
}
})
.once("error", (err) => {
console.error(err);
process.exit(1);
})
.listen(port, async () => {
console.log(`> Debugger ready on ${url}`);
console.log(`> Debug HUB URL is ${hubUrl}`);
console.log("> Opening browser...", initialUrl);
await open(initialUrl);
});