| 1 | import { statSync } from "node:fs"; |
| 2 | import { posix, win32 } from "node:path"; |
| 3 | |
| 4 | export interface ServiceBinaryLookup { |
| 5 | env: NodeJS.ProcessEnv; |
| 6 | platform: NodeJS.Platform; |
| 7 | execPath: string; |
| 8 | resourcesPath: string; |
| 9 | isFile?: (path: string) => boolean; |
| 10 | } |
| 11 | |
| 12 | export interface ServiceBinaryResolution { |
| 13 | binary: string; |
| 14 | probed: string[]; |
| 15 | } |
| 16 | |
| 17 | const DEB_SHELL_DIR = "/usr/lib/reasonix"; |
| 18 | |
| 19 | function isRegularFile(path: string): boolean { |
| 20 | try { return statSync(path).isFile(); } catch { return false; } |
| 21 | } |
| 22 | |
| 23 | // Inverse of the Go service's shellPathForExecutable (desktop/shell_bootstrap.go). |
| 24 | // The service normally hands its own path over in REASONIX_DESKTOP_SERVICE; a |
| 25 | // shell started directly (pinned taskbar icon, double-click) must find it. |
| 26 | export function resolveServiceBinary({ env, platform, execPath, resourcesPath, isFile = isRegularFile }: ServiceBinaryLookup): ServiceBinaryResolution { |
| 27 | const configured = (env.REASONIX_DESKTOP_SERVICE ?? "").trim(); |
| 28 | if (configured !== "") return { binary: configured, probed: [] }; |
| 29 | const path = platform === "win32" ? win32 : posix; |
| 30 | const name = platform === "win32" ? "reasonix-desktop.exe" : "reasonix-desktop"; |
| 31 | const bundled = path.join(resourcesPath, "service", name); |
| 32 | const candidates: string[] = []; |
| 33 | const appDir = path.dirname(execPath); |
| 34 | if (path.basename(appDir).toLowerCase() === "app") { |
| 35 | const releaseDir = path.dirname(appDir); |
| 36 | candidates.push(path.join(releaseDir, name)); |
| 37 | if (platform === "linux" && releaseDir === DEB_SHELL_DIR) candidates.push(path.join("/usr/bin", name)); |
| 38 | } |
| 39 | candidates.push(bundled); |
| 40 | return { binary: candidates.find(isFile) ?? bundled, probed: candidates }; |
| 41 | } |
| 42 |