import https from "https"; const HOST = process.env.FORTIGATE_HOST; const TOKEN = process.env.FORTIGATE_API_TOKEN; const POLL_INTERVAL_MS = 2 * 60 * 1000; // 2 minutes let cached = null; function fetchJson(urlStr, headers) { return new Promise((resolve, reject) => { const url = new URL(urlStr); const req = https.request( { hostname: url.hostname, port: url.port || 443, path: url.pathname + url.search, method: "GET", headers, rejectUnauthorized: false, }, (res) => { let body = ""; res.on("data", (chunk) => (body += chunk)); res.on("end", () => { if (res.statusCode < 200 || res.statusCode >= 300) { reject(new Error(`HTTP ${res.statusCode}`)); } else { try { resolve(JSON.parse(body)); } catch { reject(new Error("Invalid JSON in response")); } } }); } ); req.on("error", reject); req.end(); }); } function formatUptime(seconds) { const d = Math.floor(seconds / 86400); const h = Math.floor((seconds % 86400) / 3600); const m = Math.floor((seconds % 3600) / 60); if (d > 0) return `${d}d ${h}h`; if (h > 0) return `${h}h ${m}m`; return `${m}m`; } async function poll() { const headers = { Authorization: `Bearer ${TOKEN}` }; const base = `https://${HOST}`; const [statusData, resourceData] = await Promise.all([ fetchJson(`${base}/api/v2/monitor/system/status`, headers), fetchJson(`${base}/api/v2/monitor/system/resource/usage`, headers), ]); const r = statusData.results ?? {}; const nowSec = Math.floor(Date.now() / 1000); const uptimeSec = r.utc_last_reboot ? nowSec - r.utc_last_reboot : null; const cpuPct = resourceData.results?.cpu?.[0]?.current ?? null; const memPct = resourceData.results?.mem?.[0]?.current ?? null; cached = { hostname: r.hostname ?? "FortiGate", model: r.model_number ?? "1800F", version: statusData.version ?? "—", uptimeSeconds: uptimeSec, uptimeLabel: uptimeSec !== null ? formatUptime(uptimeSec) : "—", cpuPct, memPct, lastUpdated: new Date().toISOString(), }; } export function getHealth() { return cached; } export function startPolling() { if (!HOST || !TOKEN) { console.warn("[fg-health] FORTIGATE_HOST or FORTIGATE_API_TOKEN not set — health polling disabled."); return; } poll().catch((err) => console.error("[fg-health] Initial poll failed:", err.message) ); setInterval( () => poll().catch((err) => console.error("[fg-health] Poll failed:", err.message) ), POLL_INTERVAL_MS ); }