Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
2.7 kB ยท 86 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687import { Effect } from "effect";import { z } from "zod";
import { type FetchError, fetchJson } from "./fetch";import type { NormalizedComponent, SeverityLevel, StatusPageEntry, StatusType,} from "./types";
export const atlassianComponentSchema = z.object({ id: z.string(), name: z.string(), status: z.string(), description: z.string().nullable().optional(), position: z.number().optional(), group: z.boolean().optional(), group_id: z.string().nullable().optional(),});
export const atlassianComponentsResponseSchema = z.object({ components: z.array(atlassianComponentSchema),});
export type AtlassianComponent = z.infer<typeof atlassianComponentSchema>;
const STATUS_MAP: Record< string, { severity: SeverityLevel; status: StatusType }> = { operational: { severity: "none", status: "operational" }, degraded_performance: { severity: "minor", status: "degraded" }, partial_outage: { severity: "major", status: "partial_outage" }, major_outage: { severity: "critical", status: "major_outage" }, under_maintenance: { severity: "none", status: "under_maintenance" },};
function mapStatus(raw: string): { severity: SeverityLevel; status: StatusType;} { return STATUS_MAP[raw] ?? { severity: "none", status: "operational" };}
function normalizeAtlassianComponents( components: AtlassianComponent[],): NormalizedComponent[] { const groupNameById = new Map<string, string>(); for (const c of components) { if (c.group) groupNameById.set(c.id, c.name); }
const out: NormalizedComponent[] = []; for (const c of components) { // Group containers become section headers in the UI, not rows. if (c.group) continue; const { severity, status } = mapStatus(c.status); out.push({ upstreamComponentId: c.id, name: c.name, description: c.description ?? undefined, groupName: c.group_id ? groupNameById.get(c.group_id) : undefined, position: c.position ?? 0, severity, status, }); } return out;}
export const fetchAtlassianCompatibleComponents = (args: { entry: StatusPageEntry; fetcherName: string;}): Effect.Effect<NormalizedComponent[], FetchError> => { const { entry, fetcherName } = args; // `api_config.endpoint` overrides the summary URL only; components always come // from the standard `/api/v2/components.json` path under status_page_url. const url = `${entry.status_page_url}/api/v2/components.json`; return fetchJson({ url, schema: atlassianComponentsResponseSchema, fetcherName, entryId: entry.id, }).pipe(Effect.map((data) => normalizeAtlassianComponents(data.components)));};