Workflow-App/Workflow/lib/himalaya.ts
sjcoetzeesj-coder 11d0178ab1 feat: commit Workflow app source; move CIPC credentials to env
Adds the full Next.js app (app/, components/, lib/, scripts/, assets/,
docs/, Dockerfile, compose, configs) to version control.

Security:
- CIPC BizPortal customer-code logins (Login 1 + Login 3) now read
  CIPC_LOGIN1_CODE / CIPC_LOGIN1_PASSWORD / CIPC_LOGIN3_CODE /
  CIPC_LOGIN3_PASSWORD from .env.local instead of source.
- BizPortal personal login in apply-bizportal route reads
  BIZPORTAL_ID_NO / BIZPORTAL_PASSWORD.
- Added .env.example as the committed template.

.gitignore excludes .env*, node_modules, .next, logs, sqlite, Playwright
storage_state.json (live CIPC cookies), scratch dirs, client PDFs and
debug screenshots.
2026-10-18 15:21:45 +02:00

51 lines
No EOL
2 KiB
TypeScript

// 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];
}