const STATUS_API = "https://status.claude.com/api/v2/summary.json";
/**
* Fetch all components from status.claude.com (excludes group-level entries)
*/
export async function fetchAllComponents() {
const res = await fetch(STATUS_API);
if (!res.ok) throw new Error(`Status API returned ${res.status}`);
const data = await res.json();
return data.components.filter((c) => !c.group);
}
/**
* Fuzzy match a component by name (case-insensitive includes)
*/
export async function fetchComponentByName(name) {
const components = await fetchAllComponents();
return components.find((c) =>
c.name.toLowerCase().includes(name.toLowerCase())
);
}
/**
* Human-readable status label
*/
export function humanizeStatus(status) {
const map = {
operational: "Operational",
degraded_performance: "Degraded Performance",
partial_outage: "Partial Outage",
major_outage: "Major Outage",
under_maintenance: "Under Maintenance",
investigating: "Investigating",
identified: "Identified",
monitoring: "Monitoring",
resolved: "Resolved",
};
return map[status] || status;
}
/**
* Escape HTML special chars for Telegram's HTML parse mode
*/
export function escapeHtml(s) {
return s?.replace(/&/g, "&").replace(//g, ">") ?? "";
}
/**
* Format a single component as HTML line
*/
export function formatComponentLine(component) {
return `${escapeHtml(component.name)}: ${humanizeStatus(component.status)}`;
}