mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 12:22:14 +03:00
* fix(cli): use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command Extract resolveOpenCommand(platform, url) as an exported pure function so tests import the actual production code instead of duplicating logic. The openFallback function in bin/cli/commands/dashboard.mjs used cmd /c start to open the dashboard URL on Windows, spawning an unnecessary cmd.exe process. Replaces with rundll32 url.dll,FileProtocolHandler which opens the URL directly through the Windows shell handler API without any shell wrapper. Tests: 5 tests importing the actual resolveOpenCommand function, covering all platform branches (darwin, win32, linux) and URL pass-through. Changelog fragment included. * chore: rename changelog fragment 7842->7844 to match actual PR number --------- Co-authored-by: tientien17 <tientien17@users.noreply.github.com>
71 lines
2.3 KiB
JavaScript
71 lines
2.3 KiB
JavaScript
import { execFile } from "node:child_process";
|
|
import { t } from "../i18n.mjs";
|
|
|
|
function parsePort(value, fallback) {
|
|
const parsed = parseInt(String(value), 10);
|
|
return Number.isFinite(parsed) && parsed > 0 && parsed <= 65535 ? parsed : fallback;
|
|
}
|
|
|
|
export function registerDashboard(program) {
|
|
program
|
|
.command("dashboard")
|
|
.description(t("dashboard.description"))
|
|
.option("--url", t("dashboard.urlOnly"))
|
|
.option("--port <port>", "Port the server is running on")
|
|
.option("--tui", t("dashboard.tui") || "Open interactive TUI dashboard (terminal UI)")
|
|
.action(async (opts, cmd) => {
|
|
if (opts.tui) {
|
|
const globalOpts = cmd.optsWithGlobals();
|
|
const port = parsePort(opts.port ?? process.env.PORT ?? "20128", 20128);
|
|
const baseUrl = globalOpts.baseUrl ?? `http://localhost:${port}`;
|
|
const apiKey = globalOpts.apiKey ?? null;
|
|
const { startInteractiveTui } = await import("../tui/Dashboard.jsx");
|
|
await startInteractiveTui({ port, baseUrl, apiKey });
|
|
return;
|
|
}
|
|
const exitCode = await runDashboardCommand(opts);
|
|
if (exitCode !== 0) process.exit(exitCode);
|
|
});
|
|
}
|
|
|
|
export async function runDashboardCommand(opts = {}) {
|
|
const port = parsePort(opts.port ?? process.env.PORT ?? "20128", 20128);
|
|
const dashboardUrl = `http://localhost:${port}`;
|
|
|
|
if (opts.url) {
|
|
console.log(dashboardUrl);
|
|
return 0;
|
|
}
|
|
|
|
console.log(t("dashboard.opening", { url: dashboardUrl }));
|
|
|
|
try {
|
|
const open = await import("open");
|
|
await open.default(dashboardUrl);
|
|
} catch {
|
|
await openFallback(dashboardUrl);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Resolve the command and args to open a URL in the default browser
|
|
* for a given platform. Exported for testing — callers should use openFallback().
|
|
* @param {"darwin"|"win32"|string} platform
|
|
* @param {string} url
|
|
* @returns {{ cmd: string, args: string[] }}
|
|
*/
|
|
export function resolveOpenCommand(platform, url) {
|
|
if (platform === "darwin") return { cmd: "open", args: [url] };
|
|
if (platform === "win32") return { cmd: "rundll32", args: ["url.dll,FileProtocolHandler", url] };
|
|
return { cmd: "xdg-open", args: [url] };
|
|
}
|
|
|
|
function openFallback(url) {
|
|
return new Promise((resolve) => {
|
|
const { cmd, args } = resolveOpenCommand(process.platform, url);
|
|
execFile(cmd, args, { stdio: "ignore" }, () => resolve());
|
|
});
|
|
}
|