// Generated by scripts/codegen.mjs. DO NOT EDIT. // ============================================================================ // THIS FILE IS GENERATED. DO NOT EDIT IT DIRECTLY. // Instead, edit scripts/codegen/templates/pi-ext-browser-open.ts. // Then run: mise run //:codegen // ============================================================================ import { spawn } from "node:child_process"; export type BrowserUrlOpenerOptions = { platform?: NodeJS.Platform; env?: NodeJS.ProcessEnv; timeoutMs?: number; candidates?: BrowserOpenerCandidate[]; }; export type BrowserOpenerCandidate = { command: string; args: string[]; windowsHide?: boolean; }; /** Open a URL through platform-native handlers. Returns selected command. */ export async function openUrl( url: string, options: BrowserUrlOpenerOptions, ): Promise { for (const candidate of options.candidates ?? openerCandidates(url, options)) { if (await trySpawn(candidate, options)) return candidate.command; } return undefined; } export function openerCandidates( url: string, options: Pick = {}, ): BrowserOpenerCandidate[] { const platform = options.platform ?? process.platform; const env = options.env ?? process.env; if (env.TERMUX_VERSION) return [{ command: "termux-open-url", args: [url] }]; if (platform === "darwin") return [{ command: "open", args: [url] }]; if (platform === "win32") return [ { command: "rundll32.exe", args: ["url.dll,FileProtocolHandler", url], windowsHide: true, }, ]; return [ { command: "xdg-open", args: [url] }, { command: "wslview", args: [url] }, { command: "gio", args: ["open", url] }, ]; } function trySpawn( candidate: BrowserOpenerCandidate, options: BrowserUrlOpenerOptions, ): Promise { return new Promise((resolve) => { const child = spawn(candidate.command, candidate.args, { detached: true, stdio: "ignore", windowsHide: candidate.windowsHide ?? true, env: options.env, }); let settled = false; const done = (ok: boolean) => { if (settled) return; settled = true; resolve(ok); }; child.once("error", () => done(false)); child.once("spawn", () => { child.unref(); done(true); }); if (options.timeoutMs !== undefined) setTimeout(() => done(false), options.timeoutMs).unref(); }); }