Skip to content

Commit 00fb84f

Browse files
committed
cleanup trigger outputs
1 parent ce38024 commit 00fb84f

32 files changed

+425
-115
lines changed

.claude/commands/add-trigger.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,53 @@ All fields automatically have:
552552
- `mode: 'trigger'` - Only shown in trigger mode
553553
- `condition: { field: 'selectedTriggerId', value: triggerId }` - Only shown when this trigger is selected
554554

555+
## Trigger Outputs & Webhook Input Formatting
556+
557+
### Important: Two Sources of Truth
558+
559+
There are two related but separate concerns:
560+
561+
1. **Trigger `outputs`** - Schema/contract defining what fields SHOULD be available. Used by UI for tag dropdown.
562+
2. **`formatWebhookInput`** - Implementation that transforms raw webhook payload into actual data. Located in `apps/sim/lib/webhooks/utils.server.ts`.
563+
564+
**These MUST be aligned.** The fields returned by `formatWebhookInput` should match what's defined in trigger `outputs`. If they differ:
565+
- Tag dropdown shows fields that don't exist (broken variable resolution)
566+
- Or actual data has fields not shown in dropdown (users can't discover them)
567+
568+
### When to Add a formatWebhookInput Handler
569+
570+
- **Simple providers**: If the raw webhook payload structure already matches your outputs, you don't need a handler. The generic fallback returns `body` directly.
571+
- **Complex providers**: If you need to transform, flatten, extract nested data, compute fields, or handle conditional logic, add a handler.
572+
573+
### Adding a Handler
574+
575+
In `apps/sim/lib/webhooks/utils.server.ts`, add a handler block:
576+
577+
```typescript
578+
if (foundWebhook.provider === '{service}') {
579+
// Transform raw webhook body to match trigger outputs
580+
return {
581+
eventType: body.type,
582+
resourceId: body.data?.id || '',
583+
timestamp: body.created_at,
584+
resource: body.data,
585+
}
586+
}
587+
```
588+
589+
**Key rules:**
590+
- Return fields that match your trigger `outputs` definition exactly
591+
- No wrapper objects like `webhook: { data: ... }` or `{service}: { ... }`
592+
- No duplication (don't spread body AND add individual fields)
593+
- Use `null` for missing optional data, not empty objects with empty strings
594+
595+
### Verify Alignment
596+
597+
Run the alignment checker:
598+
```bash
599+
bunx scripts/check-trigger-alignment.ts {service}
600+
```
601+
555602
## Trigger Outputs
556603

557604
Trigger outputs use the same schema as block outputs (NOT tool outputs).
@@ -649,6 +696,11 @@ export const {service}WebhookTrigger: TriggerConfig = {
649696
- [ ] Added `delete{Service}Webhook` function to `provider-subscriptions.ts`
650697
- [ ] Added provider to `cleanupExternalWebhook` function
651698
699+
### Webhook Input Formatting
700+
- [ ] Added handler in `apps/sim/lib/webhooks/utils.server.ts` (if custom formatting needed)
701+
- [ ] Handler returns fields matching trigger `outputs` exactly
702+
- [ ] Run `bunx scripts/check-trigger-alignment.ts {service}` to verify alignment
703+
652704
### Testing
653705
- [ ] Run `bun run type-check` to verify no TypeScript errors
654706
- [ ] Restart dev server to pick up new triggers

apps/sim/lib/webhooks/utils.server.ts

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,12 @@ async function formatTeamsGraphNotification(
423423
hasCredential: !!credentialId,
424424
})
425425
return {
426-
from: null,
427-
message: { raw: notification },
428-
activity: body,
429-
conversation: { id: chatId },
426+
message_id: resolvedMessageId,
427+
chat_id: resolvedChatId,
428+
from_name: '',
429+
text: '',
430+
created_at: '',
431+
attachments: [],
430432
}
431433
}
432434

@@ -435,31 +437,12 @@ async function formatTeamsGraphNotification(
435437
const createdAt = message.createdDateTime || ''
436438

437439
return {
438-
from: {
439-
id: from.id || '',
440-
name: from.displayName || '',
441-
aadObjectId: from.aadObjectId || '',
442-
},
443-
message: {
444-
raw: {
445-
attachments: rawAttachments,
446-
channelData: {},
447-
conversation: { id: chatId },
448-
text: messageText,
449-
messageType: 'message',
450-
channelId: '',
451-
timestamp: createdAt,
452-
},
453-
},
454-
activity: body,
455-
conversation: {
456-
id: chatId,
457-
name: '',
458-
isGroup: false,
459-
tenantId: '',
460-
aadObjectId: '',
461-
conversationType: '',
462-
},
440+
message_id: resolvedMessageId,
441+
chat_id: resolvedChatId,
442+
from_name: from.displayName || '',
443+
text: messageText,
444+
created_at: createdAt,
445+
attachments: rawAttachments,
463446
}
464447
}
465448

@@ -602,6 +585,7 @@ export async function formatWebhookInput(
602585
sender: rawMessage.from
603586
? {
604587
id: rawMessage.from.id,
588+
username: rawMessage.from.username,
605589
firstName: rawMessage.from.first_name,
606590
lastName: rawMessage.from.last_name,
607591
languageCode: rawMessage.from.language_code,
@@ -818,7 +802,7 @@ export async function formatWebhookInput(
818802
if (foundWebhook.provider === 'webflow') {
819803
return {
820804
siteId: body?.siteId || '',
821-
workspaceId: body?.workspaceId || '',
805+
formId: body?.formId || '',
822806
name: body?.name || '',
823807
id: body?.id || '',
824808
submittedAt: body?.submittedAt || '',
@@ -977,16 +961,6 @@ export async function formatWebhookInput(
977961
}
978962
}
979963

980-
if (foundWebhook.provider === 'lemlist') {
981-
// Lemlist webhook - expose raw payload as `data` for user to destructure
982-
// Common fields include: _id, type, createdAt, leadId, campaignId, leadEmail,
983-
// leadFirstName, leadLastName, sequenceStep, messageId, text, etc.
984-
return {
985-
data: body,
986-
}
987-
}
988-
989-
// Generic format for other providers - pass through the body directly
990964
return body
991965
}
992966

apps/sim/triggers/circleback/utils.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,3 @@ export function buildMeetingOutputs(): Record<string, TriggerOutput> {
9696
},
9797
} as Record<string, TriggerOutput>
9898
}
99-
100-
/**
101-
* Build output schema for generic webhook events
102-
*/
103-
export function buildGenericOutputs(): Record<string, TriggerOutput> {
104-
return {
105-
payload: {
106-
type: 'object',
107-
description: 'Raw webhook payload',
108-
},
109-
headers: {
110-
type: 'object',
111-
description: 'Request headers',
112-
},
113-
timestamp: {
114-
type: 'string',
115-
description: 'ISO8601 received timestamp',
116-
},
117-
} as Record<string, TriggerOutput>
118-
}

apps/sim/triggers/circleback/webhook.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CirclebackIcon } from '@/components/icons'
22
import type { TriggerConfig } from '@/triggers/types'
3-
import { buildGenericOutputs, circlebackSetupInstructions, circlebackTriggerOptions } from './utils'
3+
import { buildMeetingOutputs, circlebackSetupInstructions, circlebackTriggerOptions } from './utils'
44

55
export const circlebackWebhookTrigger: TriggerConfig = {
66
id: 'circleback_webhook',
@@ -74,7 +74,7 @@ export const circlebackWebhookTrigger: TriggerConfig = {
7474
},
7575
],
7676

77-
outputs: buildGenericOutputs(),
77+
outputs: buildMeetingOutputs(),
7878

7979
webhook: {
8080
method: 'POST',

apps/sim/triggers/github/issue_closed.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ export const githubIssueClosedTrigger: TriggerConfig = {
116116
],
117117

118118
outputs: {
119+
event_type: {
120+
type: 'string',
121+
description:
122+
'GitHub event type from X-GitHub-Event header (e.g., issues, pull_request, push)',
123+
},
124+
branch: {
125+
type: 'string',
126+
description: 'Branch name derived from ref (empty for non-branch events)',
127+
},
119128
action: {
120129
type: 'string',
121130
description: 'Action performed (opened, closed, reopened, edited, etc.)',

apps/sim/triggers/github/issue_comment.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ export const githubIssueCommentTrigger: TriggerConfig = {
117117
],
118118

119119
outputs: {
120+
event_type: {
121+
type: 'string',
122+
description: 'GitHub event type from X-GitHub-Event header (e.g., issue_comment)',
123+
},
124+
branch: {
125+
type: 'string',
126+
description: 'Branch name derived from ref (empty for non-branch events)',
127+
},
120128
action: {
121129
type: 'string',
122130
description: 'Action performed (created, edited, deleted)',

apps/sim/triggers/github/issue_opened.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,15 @@ export const githubIssueOpenedTrigger: TriggerConfig = {
137137
],
138138

139139
outputs: {
140+
event_type: {
141+
type: 'string',
142+
description:
143+
'GitHub event type from X-GitHub-Event header (e.g., issues, pull_request, push)',
144+
},
145+
branch: {
146+
type: 'string',
147+
description: 'Branch name derived from ref (empty for non-branch events)',
148+
},
140149
action: {
141150
type: 'string',
142151
description: 'Action performed (opened, closed, reopened, edited, etc.)',

apps/sim/triggers/github/pr_closed.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ export const githubPRClosedTrigger: TriggerConfig = {
117117
],
118118

119119
outputs: {
120+
event_type: {
121+
type: 'string',
122+
description: 'GitHub event type from X-GitHub-Event header (e.g., pull_request)',
123+
},
124+
branch: {
125+
type: 'string',
126+
description: 'Branch name derived from ref (empty for non-branch events)',
127+
},
120128
action: {
121129
type: 'string',
122130
description: 'Action performed (opened, closed, synchronize, reopened, edited, etc.)',

apps/sim/triggers/github/pr_comment.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ export const githubPRCommentTrigger: TriggerConfig = {
117117
],
118118

119119
outputs: {
120+
event_type: {
121+
type: 'string',
122+
description: 'GitHub event type from X-GitHub-Event header (e.g., issue_comment)',
123+
},
124+
branch: {
125+
type: 'string',
126+
description: 'Branch name derived from ref (empty for non-branch events)',
127+
},
120128
action: {
121129
type: 'string',
122130
description: 'Action performed (created, edited, deleted)',

apps/sim/triggers/github/pr_merged.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ export const githubPRMergedTrigger: TriggerConfig = {
116116
],
117117

118118
outputs: {
119+
event_type: {
120+
type: 'string',
121+
description: 'GitHub event type from X-GitHub-Event header (e.g., pull_request)',
122+
},
123+
branch: {
124+
type: 'string',
125+
description: 'Branch name derived from ref (empty for non-branch events)',
126+
},
119127
action: {
120128
type: 'string',
121129
description: 'Action performed (opened, closed, synchronize, reopened, edited, etc.)',

0 commit comments

Comments
 (0)