import fs from "node:fs"; import path from "node:path"; import { app } from "electron"; export type TrayAccount = { email: string; label: string; /** Electron session partition name — one browser profile per account */ partition: string; }; export type TrayConfig = { apiUrl: string; trayKey: string; accounts: TrayAccount[]; lastPushAt?: string; lastPushSummary?: string; lastError?: string; }; const DEFAULT_CONFIG: TrayConfig = { apiUrl: "http://localhost:3000", trayKey: "", accounts: [], }; export function configPath(): string { return path.join(app.getPath("userData"), "tray-config.json"); } export function loadConfig(): TrayConfig { const file = configPath(); try { if (!fs.existsSync(file)) return { ...DEFAULT_CONFIG, accounts: [] }; const raw = JSON.parse(fs.readFileSync(file, "utf8")) as Partial; return { apiUrl: String(raw.apiUrl ?? DEFAULT_CONFIG.apiUrl).replace(/\/$/, ""), trayKey: String(raw.trayKey ?? ""), accounts: Array.isArray(raw.accounts) ? raw.accounts .map((a) => ({ email: String(a.email ?? "") .trim() .toLowerCase(), label: String(a.label ?? "").trim(), partition: String(a.partition ?? "").trim() || `vp-${Math.random().toString(36).slice(2, 10)}`, })) .filter((a) => a.email) : [], lastPushAt: typeof raw.lastPushAt === "string" ? raw.lastPushAt : undefined, lastPushSummary: typeof raw.lastPushSummary === "string" ? raw.lastPushSummary : undefined, lastError: typeof raw.lastError === "string" ? raw.lastError : undefined, }; } catch { return { ...DEFAULT_CONFIG, accounts: [] }; } } export function saveConfig(cfg: TrayConfig): void { const file = configPath(); fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, JSON.stringify(cfg, null, 2), "utf8"); }