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.6 kB ยท 85 lines
TypeScript
at incident-api
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586import { and, eq } from "@openstatus/db";import { pageSubscriber } from "@openstatus/db/src/schema";import { detectWebhookFlavor, sendTestWebhookRequest,} from "@openstatus/subscriptions";
import { requireScope } from "../auth";import { type ServiceContext, withTransaction } from "../context";import { NotFoundError, ValidationError } from "../errors";import { loadPageForWorkspace } from "./internal";import { SendPageSubscriberTestWebhookInput } from "./schemas";
/** * Send a test payload to a vendor-added webhook subscriber. * * No audit emit โ a test dispatch has no effect on the entity's durable * state. If we add "last-tested-at" bookkeeping later, we'd revisit. */// The transaction only reads the subscriber row; the webhook send mutates// nothing, so there is no state change to audit.// oxlint-disable-next-line openstatus/services-mutation-guardsexport async function sendPageSubscriberTestWebhook(args: { ctx: ServiceContext; input: SendPageSubscriberTestWebhookInput;}): Promise<void> { const { ctx } = args; requireScope(ctx, "write"); const input = SendPageSubscriberTestWebhookInput.parse(args.input);
const existing = await withTransaction(ctx, async (tx) => { await loadPageForWorkspace({ tx, pageId: input.pageId, workspaceId: ctx.workspace.id, }); return tx.query.pageSubscriber.findFirst({ where: and( eq(pageSubscriber.id, input.subscriberId), eq(pageSubscriber.pageId, input.pageId), ), }); });
if (!existing) { throw new NotFoundError("page_subscriber", input.subscriberId); } if (existing.source !== "vendor") { throw new ValidationError( "Only vendor-added webhook subscribers support test dispatch.", ); } if (existing.channelType !== "webhook" || !existing.webhookUrl) { throw new ValidationError("Subscriber is not a webhook channel"); } if (existing.unsubscribedAt) { throw new ValidationError("Subscriber is unsubscribed"); }
const flavor = detectWebhookFlavor(existing.webhookUrl); const headers = parseWebhookHeaders(existing.channelConfig); await sendTestWebhookRequest({ url: existing.webhookUrl, flavor, headers, });}
function parseWebhookHeaders( channelConfig: string | null,): Record<string, string> { if (!channelConfig) return {}; try { const config = JSON.parse(channelConfig) as { headers?: { key: string; value: string }[]; }; const headers: Record<string, string> = {}; for (const h of config.headers ?? []) { headers[h.key] = h.value; } return headers; } catch { return {}; }}