11import type { SubBlockConfig } from '@/blocks/types'
22import type { TriggerOutput } from '@/triggers/types'
33
4- /**
5- * Shared trigger dropdown options for all Confluence triggers
6- */
74export const confluenceTriggerOptions = [
8- // Page Events
95 { label : 'Page Created' , id : 'confluence_page_created' } ,
106 { label : 'Page Updated' , id : 'confluence_page_updated' } ,
117 { label : 'Page Removed' , id : 'confluence_page_removed' } ,
128 { label : 'Page Moved' , id : 'confluence_page_moved' } ,
13- // Comment Events
149 { label : 'Comment Created' , id : 'confluence_comment_created' } ,
1510 { label : 'Comment Removed' , id : 'confluence_comment_removed' } ,
16- // Blog Events
1711 { label : 'Blog Post Created' , id : 'confluence_blog_created' } ,
1812 { label : 'Blog Post Updated' , id : 'confluence_blog_updated' } ,
1913 { label : 'Blog Post Removed' , id : 'confluence_blog_removed' } ,
20- // Attachment Events
2114 { label : 'Attachment Created' , id : 'confluence_attachment_created' } ,
2215 { label : 'Attachment Removed' , id : 'confluence_attachment_removed' } ,
23- // Space Events
2416 { label : 'Space Created' , id : 'confluence_space_created' } ,
2517 { label : 'Space Updated' , id : 'confluence_space_updated' } ,
26- // Label Events
2718 { label : 'Label Added' , id : 'confluence_label_added' } ,
2819 { label : 'Label Removed' , id : 'confluence_label_removed' } ,
29- // Generic
3020 { label : 'Generic Webhook (All Events)' , id : 'confluence_webhook' } ,
3121]
3222
33- /**
34- * Generates setup instructions for Confluence webhooks
35- */
3623export function confluenceSetupInstructions ( eventType : string ) : string {
3724 const instructions = [
3825 '<strong>Note:</strong> You must have admin permissions in your Confluence workspace to create webhooks. See the <a href="https://developer.atlassian.com/cloud/confluence/modules/webhook/" target="_blank" rel="noopener noreferrer">Confluence webhook documentation</a> for details.' ,
@@ -52,9 +39,6 @@ export function confluenceSetupInstructions(eventType: string): string {
5239 . join ( '' )
5340}
5441
55- /**
56- * Extra fields shared across Confluence triggers (webhook secret + optional domain)
57- */
5842export function buildConfluenceExtraFields ( triggerId : string ) : SubBlockConfig [ ] {
5943 return [
6044 {
@@ -82,10 +66,6 @@ export function buildConfluenceExtraFields(triggerId: string): SubBlockConfig[]
8266 ]
8367}
8468
85- /**
86- * Extra fields for attachment triggers that support file downloads.
87- * Adds email, API token, and include toggle on top of the base fields.
88- */
8969export function buildConfluenceAttachmentExtraFields ( triggerId : string ) : SubBlockConfig [ ] {
9070 return [
9171 ...buildConfluenceExtraFields ( triggerId ) ,
@@ -128,7 +108,6 @@ export function buildConfluenceAttachmentExtraFields(triggerId: string): SubBloc
128108
129109/**
130110 * Base webhook outputs common to all Confluence triggers.
131- * Maps to the actual top-level fields in the Confluence webhook payload.
132111 */
133112function buildBaseWebhookOutputs ( ) : Record < string , TriggerOutput > {
134113 return {
@@ -148,40 +127,38 @@ function buildBaseWebhookOutputs(): Record<string, TriggerOutput> {
148127}
149128
150129/**
151- * Shared content-entity output fields present on page, blog, comment, and attachment objects
152- * in the actual Confluence webhook payload.
130+ * Shared content-entity output fields present on page, blog, comment, and attachment objects.
153131 */
154132function buildContentEntityFields ( ) : Record < string , TriggerOutput > {
155133 return {
156134 id : { type : 'number' , description : 'Content ID' } ,
157135 title : { type : 'string' , description : 'Content title' } ,
158- contentType : { type : 'string' , description : 'Content type (page, blogpost, comment, attachment)' } ,
136+ contentType : {
137+ type : 'string' ,
138+ description : 'Content type (page, blogpost, comment, attachment)' ,
139+ } ,
159140 version : { type : 'number' , description : 'Version number' } ,
160141 spaceKey : { type : 'string' , description : 'Space key the content belongs to' } ,
161142 creatorAccountId : { type : 'string' , description : 'Account ID of the creator' } ,
162143 lastModifierAccountId : { type : 'string' , description : 'Account ID of the last modifier' } ,
163144 self : { type : 'string' , description : 'URL link to the content' } ,
164145 creationDate : { type : 'number' , description : 'Creation timestamp (Unix epoch milliseconds)' } ,
165- modificationDate : { type : 'number' , description : 'Last modification timestamp (Unix epoch milliseconds)' } ,
146+ modificationDate : {
147+ type : 'number' ,
148+ description : 'Last modification timestamp (Unix epoch milliseconds)' ,
149+ } ,
166150 }
167151}
168152
169- /**
170- * Page-related outputs for page events.
171- * Matches the actual Confluence webhook payload for page_created, page_updated, etc.
172- */
153+ /** Page-related outputs for page events. */
173154export function buildPageOutputs ( ) : Record < string , TriggerOutput > {
174155 return {
175156 ...buildBaseWebhookOutputs ( ) ,
176157 page : buildContentEntityFields ( ) ,
177158 }
178159}
179160
180- /**
181- * Comment-related outputs for comment events.
182- * Matches the actual Confluence webhook payload for comment_created, comment_removed.
183- * The comment object contains a `parent` field with the full parent page/blog object.
184- */
161+ /** Comment-related outputs for comment events. */
185162export function buildCommentOutputs ( ) : Record < string , TriggerOutput > {
186163 return {
187164 ...buildBaseWebhookOutputs ( ) ,
@@ -198,21 +175,15 @@ export function buildCommentOutputs(): Record<string, TriggerOutput> {
198175 }
199176}
200177
201- /**
202- * Blog post outputs for blog events.
203- * Matches the actual Confluence webhook payload for blog_created, blog_updated, etc.
204- */
178+ /** Blog post outputs for blog events. */
205179export function buildBlogOutputs ( ) : Record < string , TriggerOutput > {
206180 return {
207181 ...buildBaseWebhookOutputs ( ) ,
208182 blog : buildContentEntityFields ( ) ,
209183 }
210184}
211185
212- /**
213- * Attachment-related outputs for attachment events.
214- * Matches the actual Confluence webhook payload for attachment_created, attachment_removed.
215- */
186+ /** Attachment-related outputs for attachment events. */
216187export function buildAttachmentOutputs ( ) : Record < string , TriggerOutput > {
217188 return {
218189 ...buildBaseWebhookOutputs ( ) ,
@@ -234,10 +205,7 @@ export function buildAttachmentOutputs(): Record<string, TriggerOutput> {
234205 }
235206}
236207
237- /**
238- * Space-related outputs for space events.
239- * Matches the actual Confluence webhook payload for space_created, space_updated.
240- */
208+ /** Space-related outputs for space events. */
241209export function buildSpaceOutputs ( ) : Record < string , TriggerOutput > {
242210 return {
243211 ...buildBaseWebhookOutputs ( ) ,
@@ -249,10 +217,7 @@ export function buildSpaceOutputs(): Record<string, TriggerOutput> {
249217 }
250218}
251219
252- /**
253- * Label-related outputs for label events.
254- * Matches the actual Confluence webhook payload for label_added, label_removed.
255- */
220+ /** Label-related outputs for label events. */
256221export function buildLabelOutputs ( ) : Record < string , TriggerOutput > {
257222 return {
258223 ...buildBaseWebhookOutputs ( ) ,
@@ -269,10 +234,7 @@ export function buildLabelOutputs(): Record<string, TriggerOutput> {
269234 }
270235}
271236
272- /**
273- * Combined outputs for the generic webhook trigger (all events).
274- * Uses json type for entity fields since the shape varies by event type.
275- */
237+ /** Combined outputs for the generic webhook trigger (all events). */
276238export function buildGenericWebhookOutputs ( ) : Record < string , TriggerOutput > {
277239 return {
278240 ...buildBaseWebhookOutputs ( ) ,
@@ -291,9 +253,6 @@ export function buildGenericWebhookOutputs(): Record<string, TriggerOutput> {
291253 }
292254}
293255
294- /**
295- * Extracts page data from a Confluence webhook payload.
296- */
297256export function extractPageData ( body : any ) {
298257 return {
299258 timestamp : body . timestamp ,
@@ -303,9 +262,6 @@ export function extractPageData(body: any) {
303262 }
304263}
305264
306- /**
307- * Extracts comment data from a Confluence webhook payload.
308- */
309265export function extractCommentData ( body : any ) {
310266 return {
311267 timestamp : body . timestamp ,
@@ -315,9 +271,6 @@ export function extractCommentData(body: any) {
315271 }
316272}
317273
318- /**
319- * Extracts blog post data from a Confluence webhook payload.
320- */
321274export function extractBlogData ( body : any ) {
322275 return {
323276 timestamp : body . timestamp ,
@@ -327,9 +280,6 @@ export function extractBlogData(body: any) {
327280 }
328281}
329282
330- /**
331- * Extracts attachment data from a Confluence webhook payload.
332- */
333283export function extractAttachmentData ( body : any ) {
334284 return {
335285 timestamp : body . timestamp ,
@@ -339,9 +289,6 @@ export function extractAttachmentData(body: any) {
339289 }
340290}
341291
342- /**
343- * Extracts space data from a Confluence webhook payload.
344- */
345292export function extractSpaceData ( body : any ) {
346293 return {
347294 timestamp : body . timestamp ,
@@ -351,9 +298,6 @@ export function extractSpaceData(body: any) {
351298 }
352299}
353300
354- /**
355- * Extracts label data from a Confluence webhook payload.
356- */
357301export function extractLabelData ( body : any ) {
358302 return {
359303 timestamp : body . timestamp ,
@@ -365,43 +309,52 @@ export function extractLabelData(body: any) {
365309}
366310
367311/**
368- * Checks if a Confluence webhook event matches a specific trigger
312+ * Infers the entity category from a Confluence webhook payload.
313+ * Unlike Jira, Confluence payloads have no `event`/`webhookEvent` field —
314+ * we detect the category by which entity key is present in the body.
369315 */
370- export function isConfluenceEventMatch ( triggerId : string , event : string ) : boolean {
371- const eventMappings : Record < string , string [ ] > = {
372- // Page events
373- confluence_page_created : [ 'page_created' ] ,
374- confluence_page_updated : [ 'page_updated' ] ,
375- confluence_page_removed : [ 'page_removed' , 'page_trashed' ] ,
376- confluence_page_moved : [ 'page_moved' ] ,
377- // Comment events
378- confluence_comment_created : [ 'comment_created' ] ,
379- confluence_comment_removed : [ 'comment_removed' ] ,
380- // Blog events
381- confluence_blog_created : [ 'blog_created' ] ,
382- confluence_blog_updated : [ 'blog_updated' ] ,
383- confluence_blog_removed : [ 'blog_removed' , 'blog_trashed' ] ,
384- // Attachment events
385- confluence_attachment_created : [ 'attachment_created' ] ,
386- confluence_attachment_removed : [ 'attachment_removed' , 'attachment_trashed' ] ,
387- // Space events
388- confluence_space_created : [ 'space_created' ] ,
389- confluence_space_updated : [ 'space_updated' ] ,
390- // Label events
391- confluence_label_added : [ 'label_added' , 'label_created' ] ,
392- confluence_label_removed : [ 'label_removed' , 'label_deleted' ] ,
393- // Generic webhook accepts all events
394- confluence_webhook : [ '*' ] ,
316+ export function inferConfluenceEntityCategory ( body : Record < string , unknown > ) : string | null {
317+ if ( body . comment ) return 'comment'
318+ if ( body . attachment ) return 'attachment'
319+ if ( body . blog || body . blogpost ) return 'blog'
320+ if ( body . label ) return 'label'
321+ if ( body . page ) return 'page'
322+ if ( body . space ) return 'space'
323+ return null
324+ }
325+
326+ /** Checks if a Confluence webhook payload matches a trigger's expected entity category. */
327+ export function isConfluencePayloadMatch (
328+ triggerId : string ,
329+ body : Record < string , unknown >
330+ ) : boolean {
331+ if ( triggerId === 'confluence_webhook' ) {
332+ return true
395333 }
396334
397- const expectedEvents = eventMappings [ triggerId ]
398- if ( ! expectedEvents ) {
399- return false
335+ const triggerCategoryMap : Record < string , string > = {
336+ confluence_page_created : 'page' ,
337+ confluence_page_updated : 'page' ,
338+ confluence_page_removed : 'page' ,
339+ confluence_page_moved : 'page' ,
340+ confluence_comment_created : 'comment' ,
341+ confluence_comment_removed : 'comment' ,
342+ confluence_blog_created : 'blog' ,
343+ confluence_blog_updated : 'blog' ,
344+ confluence_blog_removed : 'blog' ,
345+ confluence_attachment_created : 'attachment' ,
346+ confluence_attachment_removed : 'attachment' ,
347+ confluence_space_created : 'space' ,
348+ confluence_space_updated : 'space' ,
349+ confluence_label_added : 'label' ,
350+ confluence_label_removed : 'label' ,
400351 }
401352
402- if ( expectedEvents . includes ( '*' ) ) {
403- return true
353+ const expectedCategory = triggerCategoryMap [ triggerId ]
354+ if ( ! expectedCategory ) {
355+ return false
404356 }
405357
406- return expectedEvents . includes ( event )
358+ const actualCategory = inferConfluenceEntityCategory ( body )
359+ return actualCategory === expectedCategory
407360}
0 commit comments