import type { EventBusLike } from "@suaveplan/types"; import { recordPresenceUpdate } from "../otel/otel.js"; import type { GatewayEventMap, PresenceWebhookConfig } from "../types/types.js"; import { deliverPresenceWebhook } from "./presence-webhook.js"; /** * Single presence-event side-effect helper. Emits the typed bus event, * bumps the OTel counter, and (if configured) delivers a signed * webhook. Failures from any of the three sinks are swallowed. */ export async function firePresence( deps: { readonly bus?: EventBusLike | undefined; readonly presenceWebhook?: PresenceWebhookConfig | undefined; readonly clock: () => number; }, kind: "join" | "leave" | "update", clientId: string, roomId: string | undefined, status: string ): Promise { if (kind === "update") recordPresenceUpdate("update"); if (deps.bus) { try { deps.bus.emit("ws_gateway:presence", { kind, clientId, roomId, at: deps.clock(), }); } catch { /* bus failures must not crash the daemon */ } } if (!deps.presenceWebhook) return; await deliverPresenceWebhook(deps.presenceWebhook, { kind: kind === "join" ? "presence:join" : kind === "leave" ? "presence:leave" : "presence:update", clientId, roomId, status, at: deps.clock(), }); }