From a57f83c5cd2bf6b4734f635734ac45a9ba15d5df Mon Sep 17 00:00:00 2001 From: Catherine Renelle <32781029+catrenelle@users.noreply.github.com> Date: Sun, 8 Mar 2026 10:41:47 -0400 Subject: [PATCH] Wire up webhook dispatch for all board/column/card events Co-Authored-By: Claude Opus 4.6 --- src/routes/api/boards/[boardId]/+server.ts | 2 ++ src/routes/api/boards/[boardId]/columns/+server.ts | 2 ++ .../api/boards/[boardId]/columns/[columnId]/+server.ts | 2 ++ .../boards/[boardId]/columns/[columnId]/cards/+server.ts | 2 ++ .../columns/[columnId]/cards/[cardId]/+server.ts | 9 +++++++++ 5 files changed, 17 insertions(+) diff --git a/src/routes/api/boards/[boardId]/+server.ts b/src/routes/api/boards/[boardId]/+server.ts index 7358914..d9514e6 100644 --- a/src/routes/api/boards/[boardId]/+server.ts +++ b/src/routes/api/boards/[boardId]/+server.ts @@ -5,6 +5,7 @@ import { withTenant } from '$lib/server/rls.js'; import { requireBoardView, requireBoardEditor, requireBoardOwner } from '$lib/server/guards.js'; import { broadcast } from '$lib/server/realtime.js'; import { logActivity } from '$lib/server/activity.js'; +import { dispatchWebhooks } from '$lib/server/webhooks.js'; // Get single board with all columns and cards export const GET: RequestHandler = async ({ params, locals }) => { @@ -50,6 +51,7 @@ export const PATCH: RequestHandler = async ({ params, request, locals }) => { const socketId = request.headers.get('X-Socket-ID'); broadcast(params.boardId, 'board:updated', { board: updated, socketId }); broadcast(params.boardId, 'activity:new', { boardId: params.boardId, socketId }); + dispatchWebhooks(tenant.id, 'board:updated', { boardId: params.boardId, board: updated }); return json({ board: updated }); }; diff --git a/src/routes/api/boards/[boardId]/columns/+server.ts b/src/routes/api/boards/[boardId]/columns/+server.ts index 8f57fc2..72199ac 100644 --- a/src/routes/api/boards/[boardId]/columns/+server.ts +++ b/src/routes/api/boards/[boardId]/columns/+server.ts @@ -6,6 +6,7 @@ import { withTenant } from '$lib/server/rls.js'; import { requireBoardEditor } from '$lib/server/guards.js'; import { broadcast } from '$lib/server/realtime.js'; import { logActivity } from '$lib/server/activity.js'; +import { dispatchWebhooks } from '$lib/server/webhooks.js'; // Create column export const POST: RequestHandler = async ({ params, request, locals }) => { @@ -53,6 +54,7 @@ export const POST: RequestHandler = async ({ params, request, locals }) => { const socketId = request.headers.get('X-Socket-ID'); broadcast(params.boardId, 'column:created', { column, socketId }); broadcast(params.boardId, 'activity:new', { boardId: params.boardId, socketId }); + dispatchWebhooks(tenant.id, 'column:created', { boardId: params.boardId, column }); return json({ column }, { status: 201 }); }; diff --git a/src/routes/api/boards/[boardId]/columns/[columnId]/+server.ts b/src/routes/api/boards/[boardId]/columns/[columnId]/+server.ts index f5f4434..f9c21ab 100644 --- a/src/routes/api/boards/[boardId]/columns/[columnId]/+server.ts +++ b/src/routes/api/boards/[boardId]/columns/[columnId]/+server.ts @@ -5,6 +5,7 @@ import { withTenant } from '$lib/server/rls.js'; import { requireColumnEditor } from '$lib/server/guards.js'; import { broadcast } from '$lib/server/realtime.js'; import { logActivity } from '$lib/server/activity.js'; +import { dispatchWebhooks } from '$lib/server/webhooks.js'; // Update column title or position export const PATCH: RequestHandler = async ({ params, request, locals }) => { @@ -78,6 +79,7 @@ export const DELETE: RequestHandler = async ({ params, request, locals }) => { const socketId = request.headers.get('X-Socket-ID'); broadcast(params.boardId, 'column:deleted', { columnId: params.columnId, socketId }); broadcast(params.boardId, 'activity:new', { boardId: params.boardId, socketId }); + dispatchWebhooks(tenant.id, 'column:deleted', { boardId: params.boardId, columnId: params.columnId }); return json({ ok: true }); }; diff --git a/src/routes/api/boards/[boardId]/columns/[columnId]/cards/+server.ts b/src/routes/api/boards/[boardId]/columns/[columnId]/cards/+server.ts index 9a5304c..7ee1ba7 100644 --- a/src/routes/api/boards/[boardId]/columns/[columnId]/cards/+server.ts +++ b/src/routes/api/boards/[boardId]/columns/[columnId]/cards/+server.ts @@ -7,6 +7,7 @@ import { requireColumnEditor } from '$lib/server/guards.js'; import { broadcast } from '$lib/server/realtime.js'; import { logActivity } from '$lib/server/activity.js'; import { runAutomations } from '$lib/server/automations.js'; +import { dispatchWebhooks } from '$lib/server/webhooks.js'; // Create card in column export const POST: RequestHandler = async ({ params, request, locals }) => { @@ -75,6 +76,7 @@ export const POST: RequestHandler = async ({ params, request, locals }) => { const socketId = request.headers.get('X-Socket-ID'); broadcast(params.boardId, 'card:created', { card, columnId: params.columnId, socketId }); broadcast(params.boardId, 'activity:new', { boardId: params.boardId, socketId }); + dispatchWebhooks(tenant.id, 'card:created', { boardId: params.boardId, columnId: params.columnId, card }); return json({ card }, { status: 201 }); }; diff --git a/src/routes/api/boards/[boardId]/columns/[columnId]/cards/[cardId]/+server.ts b/src/routes/api/boards/[boardId]/columns/[columnId]/cards/[cardId]/+server.ts index db7378f..d76b871 100644 --- a/src/routes/api/boards/[boardId]/columns/[columnId]/cards/[cardId]/+server.ts +++ b/src/routes/api/boards/[boardId]/columns/[columnId]/cards/[cardId]/+server.ts @@ -8,6 +8,7 @@ import { broadcast } from '$lib/server/realtime.js'; import { logActivity } from '$lib/server/activity.js'; import { notifyWatchers } from '$lib/server/notifications.js'; import { runAutomations } from '$lib/server/automations.js'; +import { dispatchWebhooks } from '$lib/server/webhooks.js'; // Get single card with full details export const GET: RequestHandler = async ({ params, locals }) => { @@ -182,6 +183,13 @@ export const PATCH: RequestHandler = async ({ params, request, locals }) => { broadcast(params.boardId, 'card:updated', { card: updated, cardId: params.cardId, columnId: params.columnId, socketId }); broadcast(params.boardId, 'activity:new', { boardId: params.boardId, cardId: params.cardId, socketId }); + // Dispatch webhook — use card:moved if column changed, otherwise card:updated + if (body.columnId !== undefined) { + dispatchWebhooks(tenant.id, 'card:moved', { boardId: params.boardId, cardId: params.cardId, card: updated }); + } else { + dispatchWebhooks(tenant.id, 'card:updated', { boardId: params.boardId, cardId: params.cardId, card: updated }); + } + return json({ card: updated }); }; @@ -206,6 +214,7 @@ export const DELETE: RequestHandler = async ({ params, request, locals }) => { const socketId = request.headers.get('X-Socket-ID'); broadcast(params.boardId, 'card:deleted', { cardId: params.cardId, columnId: params.columnId, socketId }); broadcast(params.boardId, 'activity:new', { boardId: params.boardId, socketId }); + dispatchWebhooks(tenant.id, 'card:deleted', { boardId: params.boardId, cardId: params.cardId, columnId: params.columnId }); return json({ ok: true }); };