chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildDeploymentOutputs,
|
||||
buildVercelExtraFields,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel Deployment Canceled Trigger
|
||||
*/
|
||||
export const vercelDeploymentCanceledTrigger: TriggerConfig = {
|
||||
id: 'vercel_deployment_canceled',
|
||||
name: 'Vercel Deployment Canceled',
|
||||
provider: 'vercel',
|
||||
description: 'Trigger workflow when a deployment is canceled',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_deployment_canceled',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
setupInstructions: vercelSetupInstructions('Deployment Canceled'),
|
||||
extraFields: buildVercelExtraFields('vercel_deployment_canceled'),
|
||||
}),
|
||||
|
||||
outputs: buildDeploymentOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildDeploymentOutputs,
|
||||
buildVercelExtraFields,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel Deployment Created Trigger
|
||||
*
|
||||
* This is the PRIMARY trigger - it includes the dropdown for selecting trigger type.
|
||||
*/
|
||||
export const vercelDeploymentCreatedTrigger: TriggerConfig = {
|
||||
id: 'vercel_deployment_created',
|
||||
name: 'Vercel Deployment Created',
|
||||
provider: 'vercel',
|
||||
description: 'Trigger workflow when a new deployment is created',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_deployment_created',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
includeDropdown: true,
|
||||
setupInstructions: vercelSetupInstructions('Deployment Created'),
|
||||
extraFields: buildVercelExtraFields('vercel_deployment_created'),
|
||||
}),
|
||||
|
||||
outputs: buildDeploymentOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildDeploymentOutputs,
|
||||
buildVercelExtraFields,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel Deployment Error Trigger
|
||||
*/
|
||||
export const vercelDeploymentErrorTrigger: TriggerConfig = {
|
||||
id: 'vercel_deployment_error',
|
||||
name: 'Vercel Deployment Error',
|
||||
provider: 'vercel',
|
||||
description: 'Trigger workflow when a deployment fails',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_deployment_error',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
setupInstructions: vercelSetupInstructions('Deployment Error'),
|
||||
extraFields: buildVercelExtraFields('vercel_deployment_error'),
|
||||
}),
|
||||
|
||||
outputs: buildDeploymentOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildDeploymentOutputs,
|
||||
buildVercelExtraFields,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel Deployment Ready Trigger
|
||||
*/
|
||||
export const vercelDeploymentReadyTrigger: TriggerConfig = {
|
||||
id: 'vercel_deployment_ready',
|
||||
name: 'Vercel Deployment Ready',
|
||||
provider: 'vercel',
|
||||
description: 'Trigger workflow when a deployment is ready to serve traffic',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_deployment_ready',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
setupInstructions: vercelSetupInstructions('Deployment Ready'),
|
||||
extraFields: buildVercelExtraFields('vercel_deployment_ready'),
|
||||
}),
|
||||
|
||||
outputs: buildDeploymentOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildDomainOutputs,
|
||||
buildVercelExtraFields,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel Domain Created Trigger
|
||||
*/
|
||||
export const vercelDomainCreatedTrigger: TriggerConfig = {
|
||||
id: 'vercel_domain_created',
|
||||
name: 'Vercel Domain Created',
|
||||
provider: 'vercel',
|
||||
description: 'Trigger workflow when a domain is created',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_domain_created',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
setupInstructions: vercelSetupInstructions('Domain Created'),
|
||||
extraFields: buildVercelExtraFields('vercel_domain_created'),
|
||||
}),
|
||||
|
||||
outputs: buildDomainOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Vercel Triggers
|
||||
* Export all Vercel webhook triggers
|
||||
*/
|
||||
|
||||
export { vercelDeploymentCanceledTrigger } from './deployment_canceled'
|
||||
export { vercelDeploymentCreatedTrigger } from './deployment_created'
|
||||
export { vercelDeploymentErrorTrigger } from './deployment_error'
|
||||
export { vercelDeploymentReadyTrigger } from './deployment_ready'
|
||||
export { vercelDomainCreatedTrigger } from './domain_created'
|
||||
export { vercelProjectCreatedTrigger } from './project_created'
|
||||
export { vercelProjectRemovedTrigger } from './project_removed'
|
||||
export { vercelWebhookTrigger } from './webhook'
|
||||
@@ -0,0 +1,37 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildProjectOutputs,
|
||||
buildVercelExtraFields,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel Project Created Trigger
|
||||
*/
|
||||
export const vercelProjectCreatedTrigger: TriggerConfig = {
|
||||
id: 'vercel_project_created',
|
||||
name: 'Vercel Project Created',
|
||||
provider: 'vercel',
|
||||
description: 'Trigger workflow when a new project is created',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_project_created',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
setupInstructions: vercelSetupInstructions('Project Created'),
|
||||
extraFields: buildVercelExtraFields('vercel_project_created'),
|
||||
}),
|
||||
|
||||
outputs: buildProjectOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildProjectOutputs,
|
||||
buildVercelExtraFields,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel Project Removed Trigger
|
||||
*/
|
||||
export const vercelProjectRemovedTrigger: TriggerConfig = {
|
||||
id: 'vercel_project_removed',
|
||||
name: 'Vercel Project Removed',
|
||||
provider: 'vercel',
|
||||
description: 'Trigger workflow when a project is removed',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_project_removed',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
setupInstructions: vercelSetupInstructions('Project Removed'),
|
||||
extraFields: buildVercelExtraFields('vercel_project_removed'),
|
||||
}),
|
||||
|
||||
outputs: buildProjectOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @vitest-environment node
|
||||
*/
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { vercelHandler } from '@/lib/webhooks/providers/vercel'
|
||||
import { isVercelEventMatch } from '@/triggers/vercel/utils'
|
||||
|
||||
describe('isVercelEventMatch', () => {
|
||||
it('matches specialized triggers to Vercel type strings', () => {
|
||||
expect(isVercelEventMatch('vercel_deployment_created', 'deployment.created')).toBe(true)
|
||||
expect(isVercelEventMatch('vercel_deployment_created', 'deployment.ready')).toBe(false)
|
||||
})
|
||||
|
||||
it('does not match unknown trigger ids', () => {
|
||||
expect(isVercelEventMatch('vercel_unknown_trigger', 'deployment.created')).toBe(false)
|
||||
})
|
||||
|
||||
it('allows any event type for the curated generic trigger id', () => {
|
||||
expect(isVercelEventMatch('vercel_webhook', 'deployment.succeeded')).toBe(true)
|
||||
expect(isVercelEventMatch('vercel_webhook', undefined)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('vercelHandler.formatInput', () => {
|
||||
it('passes through documented deployment links, regions, meta, and domain.delegated', async () => {
|
||||
const { input } = await vercelHandler.formatInput!({
|
||||
webhook: {},
|
||||
workflow: { id: 'w', userId: 'u' },
|
||||
body: {
|
||||
type: 'deployment.created',
|
||||
id: 'evt_1',
|
||||
createdAt: 1_700_000_000_000,
|
||||
region: 'iad1',
|
||||
payload: {
|
||||
deployment: {
|
||||
id: 'd1',
|
||||
url: 'https://x.vercel.app',
|
||||
name: 'x',
|
||||
meta: { k: 'v' },
|
||||
},
|
||||
links: { deployment: 'https://vercel.com/d', project: 'https://vercel.com/p' },
|
||||
regions: ['iad1', 'sfo1'],
|
||||
domain: { name: 'example.com', delegated: true },
|
||||
},
|
||||
},
|
||||
headers: {},
|
||||
requestId: 't',
|
||||
})
|
||||
const i = input as Record<string, unknown>
|
||||
expect(i.links).toEqual({
|
||||
deployment: 'https://vercel.com/d',
|
||||
project: 'https://vercel.com/p',
|
||||
})
|
||||
expect(i.regions).toEqual(['iad1', 'sfo1'])
|
||||
expect(i.deployment).toMatchObject({
|
||||
id: 'd1',
|
||||
meta: { k: 'v' },
|
||||
})
|
||||
expect(i.domain).toMatchObject({ name: 'example.com', delegated: true })
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,309 @@
|
||||
import type { SubBlockConfig } from '@/blocks/types'
|
||||
import type { TriggerOutput } from '@/triggers/types'
|
||||
|
||||
/**
|
||||
* Dropdown options for the Vercel trigger type selector
|
||||
*/
|
||||
export const vercelTriggerOptions = [
|
||||
{ label: 'Deployment Created', id: 'vercel_deployment_created' },
|
||||
{ label: 'Deployment Ready', id: 'vercel_deployment_ready' },
|
||||
{ label: 'Deployment Error', id: 'vercel_deployment_error' },
|
||||
{ label: 'Deployment Canceled', id: 'vercel_deployment_canceled' },
|
||||
{ label: 'Project Created', id: 'vercel_project_created' },
|
||||
{ label: 'Project Removed', id: 'vercel_project_removed' },
|
||||
{ label: 'Domain Created', id: 'vercel_domain_created' },
|
||||
{ label: 'Common events (curated list)', id: 'vercel_webhook' },
|
||||
]
|
||||
|
||||
/** Maps Sim trigger IDs to Vercel webhook `type` strings (see Vercel Webhooks API). */
|
||||
export const VERCEL_TRIGGER_EVENT_TYPES: Record<string, string> = {
|
||||
vercel_deployment_created: 'deployment.created',
|
||||
vercel_deployment_ready: 'deployment.ready',
|
||||
vercel_deployment_error: 'deployment.error',
|
||||
vercel_deployment_canceled: 'deployment.canceled',
|
||||
vercel_project_created: 'project.created',
|
||||
vercel_project_removed: 'project.removed',
|
||||
vercel_domain_created: 'domain.created',
|
||||
}
|
||||
|
||||
/** Curated set used by the generic Vercel webhook trigger. */
|
||||
export const VERCEL_GENERIC_TRIGGER_EVENT_TYPES = [
|
||||
'deployment.created',
|
||||
'deployment.ready',
|
||||
'deployment.succeeded',
|
||||
'deployment.error',
|
||||
'deployment.canceled',
|
||||
'deployment.promoted',
|
||||
'project.created',
|
||||
'project.removed',
|
||||
'domain.created',
|
||||
'edge-config.created',
|
||||
'edge-config.deleted',
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Returns whether the incoming Vercel event matches the configured trigger.
|
||||
* `vercel_webhook` is handled only at subscription time; deliveries are not filtered here.
|
||||
*/
|
||||
export function isVercelEventMatch(triggerId: string, eventType: string | undefined): boolean {
|
||||
if (triggerId === 'vercel_webhook') {
|
||||
return true
|
||||
}
|
||||
const expected = VERCEL_TRIGGER_EVENT_TYPES[triggerId]
|
||||
if (!expected) {
|
||||
return false
|
||||
}
|
||||
return eventType === expected
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates setup instructions for Vercel webhooks.
|
||||
* Webhooks are automatically created via the Vercel API.
|
||||
*/
|
||||
export function vercelSetupInstructions(eventType: string): string {
|
||||
const instructions = [
|
||||
'Enter your Vercel Access Token above.',
|
||||
'You can create a token at <strong>Vercel Dashboard > Settings > Tokens</strong>.',
|
||||
`Click <strong>"Save Configuration"</strong> to automatically create the webhook in Vercel for <strong>${eventType}</strong> events.`,
|
||||
'The webhook will be automatically deleted when you remove this trigger.',
|
||||
]
|
||||
|
||||
return instructions
|
||||
.map(
|
||||
(instruction, index) =>
|
||||
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
|
||||
)
|
||||
.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* Vercel-specific extra fields for triggers.
|
||||
* Includes API token (required) and optional project/team filters.
|
||||
*/
|
||||
export function buildVercelExtraFields(triggerId: string): SubBlockConfig[] {
|
||||
return [
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'Access Token',
|
||||
type: 'short-input' as const,
|
||||
placeholder: 'Enter your Vercel access token',
|
||||
description: 'Required to create the webhook in Vercel.',
|
||||
password: true,
|
||||
required: true,
|
||||
paramVisibility: 'user-only',
|
||||
mode: 'trigger' as const,
|
||||
condition: { field: 'selectedTriggerId', value: triggerId },
|
||||
},
|
||||
{
|
||||
id: 'teamId',
|
||||
title: 'Team ID (Optional)',
|
||||
type: 'short-input' as const,
|
||||
placeholder: 'team_xxxxx (leave empty for personal account)',
|
||||
description: 'Scope webhook to a specific team',
|
||||
mode: 'trigger' as const,
|
||||
condition: { field: 'selectedTriggerId', value: triggerId },
|
||||
},
|
||||
{
|
||||
id: 'filterProjectIds',
|
||||
title: 'Project IDs (Optional)',
|
||||
type: 'short-input' as const,
|
||||
placeholder: 'prj_xxx,prj_yyy (comma-separated)',
|
||||
description: 'Limit webhook to specific projects',
|
||||
mode: 'trigger' as const,
|
||||
condition: { field: 'selectedTriggerId', value: triggerId },
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Core outputs present in all Vercel webhook payloads
|
||||
*/
|
||||
const coreOutputs = {
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Event type (e.g., deployment.created)',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'Unique webhook delivery ID (string)',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'number',
|
||||
description: 'Event timestamp in milliseconds',
|
||||
},
|
||||
region: {
|
||||
type: 'string',
|
||||
description: 'Region where the event occurred',
|
||||
},
|
||||
} as const
|
||||
|
||||
/** Raw `payload` object from the Vercel webhook body (event-specific shape). */
|
||||
const payloadOutput = {
|
||||
payload: { type: 'json' as const, description: 'Raw event payload from Vercel' },
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Dashboard deep links included on many deployment webhook events (Vercel Webhooks API).
|
||||
*/
|
||||
const linksOutputs = {
|
||||
links: {
|
||||
deployment: {
|
||||
type: 'string',
|
||||
description: 'Vercel Dashboard URL for the deployment',
|
||||
},
|
||||
project: {
|
||||
type: 'string',
|
||||
description: 'Vercel Dashboard URL for the project',
|
||||
},
|
||||
},
|
||||
regions: {
|
||||
type: 'json',
|
||||
description: 'Regions associated with the deployment (array), when provided by Vercel',
|
||||
},
|
||||
} as const
|
||||
|
||||
/** Normalized deployment object from `formatInput` (null when no deployment on the event). */
|
||||
const deploymentResourceOutputs = {
|
||||
deployment: {
|
||||
id: { type: 'string', description: 'Deployment ID' },
|
||||
url: { type: 'string', description: 'Deployment URL' },
|
||||
name: { type: 'string', description: 'Deployment name' },
|
||||
meta: {
|
||||
type: 'json',
|
||||
description: 'Deployment metadata map (e.g. Git metadata), per Vercel Webhooks API',
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Deployment-specific output fields
|
||||
*/
|
||||
const deploymentOutputs = {
|
||||
...linksOutputs,
|
||||
...deploymentResourceOutputs,
|
||||
project: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
},
|
||||
team: {
|
||||
id: { type: 'string', description: 'Team ID' },
|
||||
},
|
||||
user: {
|
||||
id: { type: 'string', description: 'User ID' },
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
description: 'Deployment target (production, staging, or preview)',
|
||||
},
|
||||
plan: {
|
||||
type: 'string',
|
||||
description: 'Account plan type',
|
||||
},
|
||||
domain: {
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
delegated: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the domain was delegated/shared when present on the payload',
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
const deploymentTargetPlanDomain = {
|
||||
target: deploymentOutputs.target,
|
||||
plan: deploymentOutputs.plan,
|
||||
domain: deploymentOutputs.domain,
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Project-specific output fields
|
||||
*/
|
||||
const projectOutputs = {
|
||||
project: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
name: { type: 'string', description: 'Project name' },
|
||||
},
|
||||
team: {
|
||||
id: { type: 'string', description: 'Team ID' },
|
||||
},
|
||||
user: {
|
||||
id: { type: 'string', description: 'User ID' },
|
||||
},
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Domain-specific output fields
|
||||
*/
|
||||
const domainOutputs = {
|
||||
domain: {
|
||||
name: { type: 'string', description: 'Domain name' },
|
||||
delegated: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Whether the domain was delegated/shared (domain.created), per Vercel Webhooks API',
|
||||
},
|
||||
},
|
||||
project: {
|
||||
id: { type: 'string', description: 'Project ID' },
|
||||
},
|
||||
team: {
|
||||
id: { type: 'string', description: 'Team ID' },
|
||||
},
|
||||
user: {
|
||||
id: { type: 'string', description: 'User ID' },
|
||||
},
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Build outputs for deployment events
|
||||
*/
|
||||
export function buildDeploymentOutputs(): Record<string, TriggerOutput> {
|
||||
return {
|
||||
...coreOutputs,
|
||||
...payloadOutput,
|
||||
...deploymentOutputs,
|
||||
} as Record<string, TriggerOutput>
|
||||
}
|
||||
|
||||
/**
|
||||
* Build outputs for project events
|
||||
*/
|
||||
export function buildProjectOutputs(): Record<string, TriggerOutput> {
|
||||
return {
|
||||
...coreOutputs,
|
||||
...payloadOutput,
|
||||
...linksOutputs,
|
||||
...deploymentResourceOutputs,
|
||||
...projectOutputs,
|
||||
...deploymentTargetPlanDomain,
|
||||
} as Record<string, TriggerOutput>
|
||||
}
|
||||
|
||||
/**
|
||||
* Build outputs for domain events
|
||||
*/
|
||||
export function buildDomainOutputs(): Record<string, TriggerOutput> {
|
||||
return {
|
||||
...coreOutputs,
|
||||
...payloadOutput,
|
||||
...linksOutputs,
|
||||
...deploymentResourceOutputs,
|
||||
...deploymentTargetPlanDomain,
|
||||
...domainOutputs,
|
||||
} as Record<string, TriggerOutput>
|
||||
}
|
||||
|
||||
/**
|
||||
* Build outputs for the generic webhook (all events)
|
||||
*/
|
||||
export function buildVercelOutputs(): Record<string, TriggerOutput> {
|
||||
return {
|
||||
...coreOutputs,
|
||||
payload: { type: 'json', description: 'Full event payload' },
|
||||
...linksOutputs,
|
||||
...deploymentResourceOutputs,
|
||||
project: deploymentOutputs.project,
|
||||
team: deploymentOutputs.team,
|
||||
user: deploymentOutputs.user,
|
||||
...deploymentTargetPlanDomain,
|
||||
} as Record<string, TriggerOutput>
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { VercelIcon } from '@/components/icons'
|
||||
import { buildTriggerSubBlocks } from '@/triggers'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import {
|
||||
buildVercelExtraFields,
|
||||
buildVercelOutputs,
|
||||
vercelSetupInstructions,
|
||||
vercelTriggerOptions,
|
||||
} from '@/triggers/vercel/utils'
|
||||
|
||||
/**
|
||||
* Vercel webhook trigger for a curated bundle of frequent event types.
|
||||
* Vercel requires an explicit event list; this is not every event in their catalog.
|
||||
*/
|
||||
export const vercelWebhookTrigger: TriggerConfig = {
|
||||
id: 'vercel_webhook',
|
||||
name: 'Vercel Webhook (Common Events)',
|
||||
provider: 'vercel',
|
||||
description:
|
||||
'Trigger on a curated set of common Vercel events (deployments, projects, domains, edge config). Pick a specific trigger to listen to one event type only.',
|
||||
version: '1.0.0',
|
||||
icon: VercelIcon,
|
||||
|
||||
subBlocks: buildTriggerSubBlocks({
|
||||
triggerId: 'vercel_webhook',
|
||||
triggerOptions: vercelTriggerOptions,
|
||||
setupInstructions: vercelSetupInstructions(
|
||||
'common deployment, project, domain, and edge-config events'
|
||||
),
|
||||
extraFields: buildVercelExtraFields('vercel_webhook'),
|
||||
}),
|
||||
|
||||
outputs: buildVercelOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user