mirror of
https://github.com/xtr-dev/payload-automation.git
synced 2025-12-10 00:43:23 +00:00
Implement triggerField helper across all trigger modules
- Standardize virtual field creation using triggerField helper - Simplify field definitions by removing repetitive virtual field boilerplate - Use consistent naming pattern: '__trigger_' + fieldName instead of '__builtin_' - Preserve existing field conditions while adding parameter storage logic - Update all trigger field modules to use Field type consistently
This commit is contained in:
@@ -1,62 +1,27 @@
|
||||
import type { Field } from 'payload'
|
||||
import type {Field} from 'payload'
|
||||
|
||||
import type { WorkflowsPluginConfig } from '../plugin/config-types.js'
|
||||
|
||||
import {triggerField} from "./helpers.js"
|
||||
|
||||
export function getCollectionTriggerFields<T extends string>(
|
||||
collectionTriggers: WorkflowsPluginConfig<T>['collectionTriggers']
|
||||
): Field[] {
|
||||
return [
|
||||
{
|
||||
name: '__builtin_collectionSlug',
|
||||
triggerField({
|
||||
name: 'collectionSlug',
|
||||
type: 'select',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.type === 'collection-trigger',
|
||||
description: 'Collection that triggers the workflow',
|
||||
},
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
return siblingData?.parameters?.collectionSlug || undefined
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {siblingData.parameters = {}}
|
||||
siblingData.parameters.collectionSlug = value
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
options: Object.keys(collectionTriggers || {}),
|
||||
virtual: true,
|
||||
},
|
||||
{
|
||||
name: '__builtin_operation',
|
||||
}),
|
||||
triggerField({
|
||||
name: 'operation',
|
||||
type: 'select',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.type === 'collection-trigger',
|
||||
description: 'Collection operation that triggers the workflow',
|
||||
},
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
return siblingData?.parameters?.operation || undefined
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {siblingData.parameters = {}}
|
||||
siblingData.parameters.operation = value
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
options: [
|
||||
'create',
|
||||
'delete',
|
||||
'read',
|
||||
'update',
|
||||
],
|
||||
virtual: true,
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,17 @@
|
||||
import type { Field } from 'payload'
|
||||
import type {Field} from 'payload'
|
||||
|
||||
import {triggerField} from "./helpers.js"
|
||||
|
||||
export function getCronTriggerFields(): Field[] {
|
||||
return [
|
||||
{
|
||||
name: '__builtin_cronExpression',
|
||||
triggerField({
|
||||
name: 'cronExpression',
|
||||
type: 'text',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.type === 'cron-trigger',
|
||||
description: 'Cron expression for scheduled execution (e.g., "0 0 * * *" for daily at midnight)',
|
||||
placeholder: '0 0 * * *'
|
||||
},
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
return siblingData?.parameters?.cronExpression || undefined
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {siblingData.parameters = {}}
|
||||
siblingData.parameters.cronExpression = value
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
validate: (value: any, {siblingData}: any) => {
|
||||
const cronValue = value || siblingData?.parameters?.cronExpression
|
||||
if (siblingData?.type === 'cron-trigger' && !cronValue) {
|
||||
@@ -44,10 +32,9 @@ export function getCronTriggerFields(): Field[] {
|
||||
|
||||
return true
|
||||
},
|
||||
virtual: true,
|
||||
},
|
||||
{
|
||||
name: '__builtin_timezone',
|
||||
}),
|
||||
triggerField({
|
||||
name: 'timezone',
|
||||
type: 'text',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.type === 'cron-trigger',
|
||||
@@ -55,20 +42,6 @@ export function getCronTriggerFields(): Field[] {
|
||||
placeholder: 'UTC'
|
||||
},
|
||||
defaultValue: 'UTC',
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
return siblingData?.parameters?.timezone || 'UTC'
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {siblingData.parameters = {}}
|
||||
siblingData.parameters.timezone = value || 'UTC'
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
validate: (value: any, {siblingData}: any) => {
|
||||
const tzValue = value || siblingData?.parameters?.timezone
|
||||
if (siblingData?.type === 'cron-trigger' && tzValue) {
|
||||
@@ -82,7 +55,6 @@ export function getCronTriggerFields(): Field[] {
|
||||
}
|
||||
return true
|
||||
},
|
||||
virtual: true,
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
@@ -1,56 +1,28 @@
|
||||
import type { Field } from 'payload'
|
||||
import type {Field} from 'payload'
|
||||
|
||||
import {triggerField} from "./helpers.js"
|
||||
|
||||
export function getGlobalTriggerFields(): Field[] {
|
||||
return [
|
||||
{
|
||||
name: '__builtin_global',
|
||||
triggerField({
|
||||
name: 'global',
|
||||
type: 'select',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.type === 'global-trigger',
|
||||
description: 'Global that triggers the workflow',
|
||||
},
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
return siblingData?.parameters?.global || undefined
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {siblingData.parameters = {}}
|
||||
siblingData.parameters.global = value
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
options: [], // Will be populated dynamically based on available globals
|
||||
virtual: true,
|
||||
},
|
||||
{
|
||||
name: '__builtin_globalOperation',
|
||||
}),
|
||||
triggerField({
|
||||
name: 'globalOperation',
|
||||
type: 'select',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.type === 'global-trigger',
|
||||
description: 'Global operation that triggers the workflow',
|
||||
},
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
return siblingData?.parameters?.globalOperation || undefined
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {siblingData.parameters = {}}
|
||||
siblingData.parameters.globalOperation = value
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
options: [
|
||||
'update'
|
||||
],
|
||||
virtual: true,
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import type {Field, TextField, SelectField} from "payload"
|
||||
|
||||
import type {Trigger} from "./types.js"
|
||||
|
||||
type FieldWithName = TextField | SelectField | (Field & { name: string })
|
||||
|
||||
type Options = {
|
||||
slug: string,
|
||||
fields?: FieldWithName[]
|
||||
}
|
||||
|
||||
export const trigger = ({
|
||||
slug,
|
||||
fields
|
||||
}: Options): Trigger => {
|
||||
return {
|
||||
slug,
|
||||
fields: (fields || []).map(triggerField) as Field[]
|
||||
}
|
||||
}
|
||||
|
||||
export const triggerField = (field: FieldWithName): Field => ({
|
||||
...field,
|
||||
name: '__trigger_' + field.name,
|
||||
admin: {
|
||||
...(field.admin as any || {}),
|
||||
condition: (_, siblingData, __) => {
|
||||
const previous = field.admin?.condition?.call(null, _, siblingData, __)
|
||||
return previous !== false // Preserve existing condition if it exists
|
||||
},
|
||||
},
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
const parameters = siblingData?.parameters || {}
|
||||
return parameters[field.name]
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {
|
||||
siblingData.parameters = {}
|
||||
}
|
||||
siblingData.parameters[field.name] = value
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
virtual: true,
|
||||
} as Field)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import type {Field} from "payload"
|
||||
|
||||
export type Trigger = {
|
||||
slug: string
|
||||
fields: Field[]
|
||||
}
|
||||
|
||||
@@ -1,35 +1,22 @@
|
||||
import type { Field } from 'payload'
|
||||
import type {Field} from 'payload'
|
||||
|
||||
import {triggerField} from "./helpers.js"
|
||||
|
||||
export function getWebhookTriggerFields(): Field[] {
|
||||
return [
|
||||
{
|
||||
name: '__builtin_webhookPath',
|
||||
triggerField({
|
||||
name: 'webhookPath',
|
||||
type: 'text',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.type === 'webhook-trigger',
|
||||
description: 'URL path for the webhook (e.g., "my-webhook"). Full URL will be /api/workflows-webhook/my-webhook',
|
||||
},
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ siblingData }) => {
|
||||
return siblingData?.parameters?.webhookPath || undefined
|
||||
}
|
||||
],
|
||||
beforeChange: [
|
||||
({ siblingData, value }) => {
|
||||
if (!siblingData.parameters) {siblingData.parameters = {}}
|
||||
siblingData.parameters.webhookPath = value
|
||||
return undefined // Virtual field, don't store directly
|
||||
}
|
||||
]
|
||||
},
|
||||
validate: (value: any, {siblingData}: any) => {
|
||||
if (siblingData?.type === 'webhook-trigger' && !value && !siblingData?.parameters?.webhookPath) {
|
||||
return 'Webhook path is required for webhook triggers'
|
||||
}
|
||||
return true
|
||||
},
|
||||
virtual: true,
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user