// lib/himalaya.ts // SERVER-ONLY resolver for the himalaya executable. // // Why this exists: the send routes used to spawn a hardcoded macOS path // (/opt/homebrew/bin/himalaya) and then a bare "himalaya". Both fail on // Windows — the first because that path doesn't exist, the second because // a Next.js dev server captures process.env.PATH at STARTUP, so a // PATH entry added later (e.g. by [Environment]::SetEnvironmentVariable) // is invisible until the server is restarted. That produced // `Error: spawn himalaya ENOENT` while the UI still reported success. // // Resolution order: // 1. HIMALAYA_BIN — explicit override, wins if set // 2. known install locations under the user's home dir // 3. bare "himalaya" — last resort, relies on PATH // // Because 1 and 2 are pure filesystem/host checks evaluated at call time, // this works in an already-running dev server with no restart. import "server-only"; import { existsSync } from "fs"; import { join } from "path"; import { homedir, platform } from "os"; function resolve(): string { const override = process.env.HIMALAYA_BIN?.trim(); if (override) return override; if (platform() === "win32") { const base = join(homedir(), ".local", "bin"); for (const candidate of [join(base, "himalaya.exe"), join(base, "himalaya")]) { if (existsSync(candidate)) return candidate; } } return "himalaya"; } /** Absolute path (or bare name) to the himalaya binary. */ export const HIMALAYA_BIN: string = resolve(); /** Standard argument vector for sending a raw RFC 5322 message on stdin. * * v1.x syntax: `-a/--account` is a per-subcommand option, NOT a global * flag — `himalaya -a acct message send` errors with * "unexpected argument '-a' found". * * The message MUST be piped on stdin. Passing it as an argument panics * the binary (mail-parser 0.9.4 index-out-of-bounds). */ export function himalayaSendArgs(account: string): string[] { return ["message", "send", "-a", account]; }