#!/usr/bin/env node const BASE_URL = resolveBaseUrl(); const token = process.env.CAMPAIGN_RETRY_JOB_TOKEN?.trim(); const healthToken = process.env.HEALTHCHECK_TOKEN?.trim(); if (!BASE_URL) { console.error("Missing APP_URL / NEXT_PUBLIC_APP_URL / OPS_BASE_URL"); process.exit(1); } function resolveBaseUrl() { return [ process.env.OPS_BASE_URL, process.env.APP_URL, process.env.NEXT_PUBLIC_APP_URL ].map((value) => value?.trim()).find(Boolean); } function buildUrl(path) { return `${BASE_URL.replace(/\/+$/, "")}${path.startsWith("/") ? path : `/${path}`}`; } async function requestJson(url, options = {}) { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 12_000); try { const response = await fetch(url, { ...options, headers: { accept: "application/json", ...options.headers }, signal: controller.signal }); const text = await response.text(); clearTimeout(timeout); let parsed = null; try { parsed = text ? JSON.parse(text) : null; } catch { parsed = text; } return { status: response.status, ok: response.ok, data: parsed, raw: response.ok ? null : text }; } catch (error) { clearTimeout(timeout); return { status: 0, ok: false, data: null, raw: error instanceof Error ? error.message : String(error) }; } } function appendToken(url, tokenValue) { if (!tokenValue) { return url; } const parsed = new URL(url); if (!parsed.searchParams.get("token")) { parsed.searchParams.set("token", tokenValue); } return parsed.toString(); } function passFail(ok) { return ok ? "PASS" : "FAIL"; } const results = []; const checks = [ { name: "Application root", url: buildUrl("/"), headers: {} }, { name: "Health endpoint", url: buildUrl("/api/health"), headers: healthToken ? { Authorization: `Bearer ${healthToken}` } : {} }, { name: "Campaign retry job state", url: appendToken(buildUrl("/api/jobs/campaign-retry"), token), headers: token ? { Authorization: `Bearer ${token}` } : {} } ]; for (const check of checks) { const result = await requestJson(check.url, { headers: check.headers }); results.push({ ...check, result }); console.log(`[${passFail(result.ok)}] ${check.name}: ${result.status}`); } const failedChecks = results.filter((item) => !item.result.ok); if (failedChecks.length > 0) { console.error("Some health checks failed"); for (const item of failedChecks) { console.error(`- ${item.name}: ${item.result.raw || JSON.stringify(item.result.data)}`); } process.exit(1); } console.log("All checks passed.");