import { z } from "zod"; import { createAuditEntry } from "../lib/audit.js"; import type { TRPCContext } from "../trpc.js"; import { buildWebhookCreateData, buildWebhookUpdateData, createWebhookInputSchema, loadWebhookOrThrow, sendWebhookTestRequest, updateWebhookInputSchema, } from "./webhook-support.js"; export const WebhookIdInputSchema = z.object({ id: z.string(), }); export const CreateWebhookInputSchema = createWebhookInputSchema; export const UpdateWebhookProcedureInputSchema = z.object({ id: z.string(), data: updateWebhookInputSchema, }); type WebhookProcedureContext = Pick; function withAuditUser(userId: string | undefined) { return userId ? { userId } : {}; } export async function listWebhooks(ctx: WebhookProcedureContext) { return ctx.db.webhook.findMany({ orderBy: { createdAt: "desc" }, }); } export async function getWebhookById( ctx: WebhookProcedureContext, input: z.infer, ) { return loadWebhookOrThrow(ctx.db, input.id); } export async function createWebhook( ctx: WebhookProcedureContext, input: z.infer, ) { const webhook = await ctx.db.webhook.create({ data: buildWebhookCreateData(input), }); void createAuditEntry({ db: ctx.db, entityType: "Webhook", entityId: webhook.id, entityName: webhook.name, action: "CREATE", ...withAuditUser(ctx.dbUser?.id), after: webhook as unknown as Record, source: "ui", }); return webhook; } export async function updateWebhook( ctx: WebhookProcedureContext, input: z.infer, ) { const existing = await loadWebhookOrThrow(ctx.db, input.id); const updated = await ctx.db.webhook.update({ where: { id: input.id }, data: buildWebhookUpdateData(input.data), }); void createAuditEntry({ db: ctx.db, entityType: "Webhook", entityId: input.id, entityName: updated.name, action: "UPDATE", ...withAuditUser(ctx.dbUser?.id), before: existing as unknown as Record, after: updated as unknown as Record, source: "ui", }); return updated; } export async function deleteWebhook( ctx: WebhookProcedureContext, input: z.infer, ) { const existing = await loadWebhookOrThrow(ctx.db, input.id); await ctx.db.webhook.delete({ where: { id: input.id } }); void createAuditEntry({ db: ctx.db, entityType: "Webhook", entityId: input.id, entityName: existing.name, action: "DELETE", ...withAuditUser(ctx.dbUser?.id), before: existing as unknown as Record, source: "ui", }); } export async function testWebhook( ctx: WebhookProcedureContext, input: z.infer, ) { const webhook = await loadWebhookOrThrow(ctx.db, input.id); const result = await sendWebhookTestRequest(webhook); void createAuditEntry({ db: ctx.db, entityType: "Webhook", entityId: webhook.id, entityName: webhook.name, action: "UPDATE", ...withAuditUser(ctx.dbUser?.id), summary: `Tested webhook (result: ${result.success ? "success" : "failed"})`, metadata: result as unknown as Record, source: "ui", }); return result; }