@xtr-dev/payload-automation 0.0.52 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,15 +8,13 @@ A workflow automation plugin for PayloadCMS 3.x. Build visual workflows triggere
8
8
 
9
9
  ## Features
10
10
 
11
- - **Visual Workflow Builder** - Drag-and-drop workflow editor in PayloadCMS admin
12
- - **Workflow Visualizer** - React component for displaying workflows with real-time execution status
13
- - **Collection Triggers** - Run workflows when documents are created, updated, or deleted
14
- - **Webhook Triggers** - Trigger workflows via HTTP endpoints
15
- - **Step Dependencies** - Define execution order with parallel and sequential steps
16
- - **Execution Tracking** - Full history with step-by-step results, duration, and logs
17
- - **Built-in Steps** - HTTP requests, document CRUD, email sending
18
- - **Custom Steps** - Create your own step types with the step factory
19
- - **JSONata Expressions** - Powerful data transformation between steps
11
+ - 🔄 Visual workflow builder in PayloadCMS admin
12
+ - Run workflows when documents are created/updated/deleted
13
+ - 🎯 Trigger workflows via webhooks
14
+ - 📊 Track workflow execution history
15
+ - 🔧 HTTP requests, document operations, email sending
16
+ - 🔗 Use data from previous steps in templates
17
+ - ⚙️ Step dependencies with parallel and sequential execution
20
18
 
21
19
  ## Installation
22
20
 
@@ -30,20 +28,20 @@ npm install @xtr-dev/payload-automation
30
28
 
31
29
  ```typescript
32
30
  import { buildConfig } from 'payload'
33
- import { workflowsPlugin } from '@xtr-dev/payload-automation'
31
+ import { workflowsPlugin } from '@xtr-dev/payload-automation/server'
34
32
 
35
33
  export default buildConfig({
34
+ // ... your config
36
35
  plugins: [
37
36
  workflowsPlugin({
38
- enabled: true,
39
37
  collectionTriggers: {
40
- orders: true, // Enable all hooks for orders
41
- users: {
42
- afterChange: true, // Only specific hooks
38
+ posts: true, // Enable all CRUD triggers for posts
39
+ users: {
40
+ create: true, // Only enable create trigger for users
41
+ update: true
43
42
  }
44
43
  },
45
- // Register custom steps
46
- steps: [myCustomStep],
44
+ enabled: true,
47
45
  }),
48
46
  ],
49
47
  })
@@ -52,10 +50,10 @@ export default buildConfig({
52
50
  ## Imports
53
51
 
54
52
  ```typescript
55
- // Main plugin
56
- import { workflowsPlugin } from '@xtr-dev/payload-automation'
53
+ // Server plugin
54
+ import { workflowsPlugin } from '@xtr-dev/payload-automation/server'
57
55
 
58
- // Client components
56
+ // Client components
59
57
  import { StatusCell, ErrorDisplay } from '@xtr-dev/payload-automation/client'
60
58
 
61
59
  // Types
@@ -89,13 +87,84 @@ const exampleWorkflows: SeedWorkflow[] = [
89
87
  name: 'Send Email',
90
88
  type: 'send-email',
91
89
  input: {
92
- to: '$.trigger.doc.email',
90
+ to: '{{trigger.doc.email}}',
93
91
  subject: 'Welcome!',
94
92
  text: 'Thanks for joining us!',
95
93
  },
96
94
  },
97
95
  ],
98
96
  },
97
+ {
98
+ slug: 'example-order-processing',
99
+ name: 'Example: Order Processing Pipeline',
100
+ description: 'Process order with validation, inventory check, and notifications',
101
+ triggers: [
102
+ {
103
+ type: 'collection-hook',
104
+ parameters: {
105
+ collectionSlug: 'orders',
106
+ hook: 'afterChange',
107
+ },
108
+ condition: 'trigger.operation = "create"',
109
+ },
110
+ ],
111
+ steps: [
112
+ {
113
+ name: 'Validate Order',
114
+ slug: 'validate-order', // Unique identifier for this step
115
+ type: 'http-request-step',
116
+ input: {
117
+ url: 'https://api.example.com/validate',
118
+ method: 'POST',
119
+ body: {
120
+ orderId: '{{trigger.doc.id}}',
121
+ items: '{{trigger.doc.items}}',
122
+ },
123
+ },
124
+ },
125
+ {
126
+ name: 'Check Inventory',
127
+ slug: 'check-inventory',
128
+ type: 'http-request-step',
129
+ input: {
130
+ url: 'https://api.example.com/inventory/check',
131
+ method: 'POST',
132
+ body: {
133
+ items: '{{trigger.doc.items}}',
134
+ },
135
+ },
136
+ // Dependencies reference other steps by slug
137
+ dependencies: ['validate-order'],
138
+ },
139
+ {
140
+ name: 'Create Shipment',
141
+ slug: 'create-shipment',
142
+ type: 'create-document',
143
+ input: {
144
+ collection: 'shipments',
145
+ data: {
146
+ orderId: '{{trigger.doc.id}}',
147
+ status: 'pending',
148
+ items: '{{trigger.doc.items}}',
149
+ },
150
+ },
151
+ // This step waits for both validation and inventory check
152
+ dependencies: ['validate-order', 'check-inventory'],
153
+ },
154
+ {
155
+ name: 'Send Confirmation Email',
156
+ slug: 'send-email',
157
+ type: 'send-email',
158
+ input: {
159
+ to: '{{trigger.doc.customer.email}}',
160
+ subject: 'Order Confirmed',
161
+ text: 'Your order {{trigger.doc.id}} has been confirmed!',
162
+ },
163
+ // Dependencies reference step slugs
164
+ dependencies: ['create-shipment'],
165
+ },
166
+ ],
167
+ },
99
168
  ]
100
169
 
101
170
  workflowsPlugin({
@@ -114,8 +183,78 @@ Seeded workflows:
114
183
 
115
184
  See [docs/SEEDING_WORKFLOWS.md](./docs/SEEDING_WORKFLOWS.md) for detailed documentation.
116
185
 
186
+ ## Step Dependencies
187
+
188
+ Steps can declare dependencies on other steps to control execution order. Dependencies reference steps by their **slug** (not by name or index), making them stable across renames and reordering.
189
+
190
+ ### How Dependencies Work
191
+
192
+ - **Parallel Execution**: Steps without dependencies run in parallel
193
+ - **Sequential Execution**: Steps with dependencies wait for their dependencies to complete successfully
194
+ - **Multiple Dependencies**: A step can depend on multiple other steps (all must succeed)
195
+ - **Failure Handling**: If a dependency fails, the dependent step is skipped
196
+ - **Slug-based**: Dependencies reference step `slug` fields, not names or positions
197
+
198
+ ### Example: Parallel and Sequential Steps
199
+
200
+ ```typescript
201
+ steps: [
202
+ {
203
+ name: 'Fetch User Data',
204
+ slug: 'fetch-user',
205
+ type: 'http-request-step',
206
+ // No dependencies - runs immediately
207
+ },
208
+ {
209
+ name: 'Fetch Order Data',
210
+ slug: 'fetch-orders',
211
+ type: 'http-request-step',
212
+ // No dependencies - runs in parallel with fetch-user
213
+ },
214
+ {
215
+ name: 'Generate Report',
216
+ slug: 'generate-report',
217
+ type: 'http-request-step',
218
+ dependencies: ['fetch-user', 'fetch-orders'], // Reference by slug
219
+ // Waits for both API calls to complete
220
+ input: {
221
+ url: 'https://api.example.com/reports',
222
+ body: {
223
+ user: '{{steps.FetchUserData.output.user}}',
224
+ orders: '{{steps.FetchOrderData.output.orders}}',
225
+ },
226
+ },
227
+ },
228
+ ]
229
+ ```
230
+
231
+ ### Accessing Step Output
232
+
233
+ Use `{{steps.<stepName>.output.<field>}}` to reference data from completed steps:
234
+
235
+ ```typescript
236
+ {
237
+ name: 'Process Result',
238
+ slug: 'process-result',
239
+ type: 'create-document',
240
+ dependencies: ['api-call'], // Reference by slug
241
+ input: {
242
+ collection: 'results',
243
+ data: {
244
+ // Access output from the "API Call" step
245
+ apiResponse: '{{steps.APICall.output.data}}',
246
+ status: '{{steps.APICall.output.status}}',
247
+ },
248
+ },
249
+ }
250
+ ```
251
+
117
252
  ## Step Types
118
253
 
254
+ > **Note:** Steps are just regular [PayloadCMS tasks](https://payloadcms.com/docs/jobs/overview). This plugin uses Payload's built-in job queue system, so you can leverage all of Payload's task features including retries, scheduling, and monitoring. Any `TaskConfig` you create is a valid step.
255
+
256
+ The plugin comes with a few built-in step types found below.
257
+
119
258
  ### HTTP Request
120
259
  Call external APIs with full configuration:
121
260
 
@@ -156,12 +295,13 @@ Send notifications via PayloadCMS email adapter:
156
295
 
157
296
  ## Custom Steps
158
297
 
159
- Create reusable step types with the `createStep` factory:
298
+ Steps are standard PayloadCMS tasks, so creating custom steps is just defining a `TaskConfig`. No proprietary APIs to learn:
160
299
 
161
300
  ```typescript
162
- import { createStep } from '@xtr-dev/payload-automation/steps'
301
+ import type { TaskConfig } from 'payload'
163
302
 
164
- export const SlackNotificationStep = createStep({
303
+ // Define the step configuration
304
+ export const SlackNotificationStep: TaskConfig<'slack-notification'> = {
165
305
  slug: 'slack-notification',
166
306
  label: 'Send Slack Message',
167
307
 
@@ -175,42 +315,40 @@ export const SlackNotificationStep = createStep({
175
315
  { name: 'timestamp', type: 'text' },
176
316
  ],
177
317
 
178
- visual: {
179
- icon: '💬',
180
- color: '#4A154B',
181
- },
182
-
183
- validate: (input) => {
184
- if (!input.channel?.startsWith('#')) {
185
- throw new Error('Channel must start with #')
186
- }
187
- },
188
-
189
- execute: async (input, req) => {
190
- const response = await fetch('https://slack.com/api/chat.postMessage', {
191
- method: 'POST',
192
- headers: {
193
- 'Authorization': `Bearer ${process.env.SLACK_TOKEN}`,
194
- 'Content-Type': 'application/json',
195
- },
196
- body: JSON.stringify({
197
- channel: input.channel,
198
- text: input.message,
199
- }),
200
- })
201
-
202
- const data = await response.json()
203
- return {
204
- messageId: data.message.ts,
205
- timestamp: new Date().toISOString(),
318
+ handler: async ({ input, req }) => {
319
+ try {
320
+ const response = await fetch('https://slack.com/api/chat.postMessage', {
321
+ method: 'POST',
322
+ headers: {
323
+ 'Authorization': `Bearer ${process.env.SLACK_TOKEN}`,
324
+ 'Content-Type': 'application/json',
325
+ },
326
+ body: JSON.stringify({
327
+ channel: input.channel,
328
+ text: input.message,
329
+ }),
330
+ })
331
+
332
+ const data = await response.json()
333
+
334
+ return {
335
+ output: {
336
+ messageId: data.message.ts,
337
+ timestamp: new Date().toISOString(),
338
+ },
339
+ state: 'succeeded'
340
+ }
341
+ } catch (error) {
342
+ return {
343
+ output: {},
344
+ state: 'failed',
345
+ errorMessage: error instanceof Error ? error.message : 'Unknown error'
346
+ }
206
347
  }
207
348
  },
208
- })
209
- ```
210
-
211
- Register custom steps in the plugin config:
349
+ }
212
350
 
213
- ```typescript
351
+ // Register in plugin config
214
352
  workflowsPlugin({
215
353
  steps: [SlackNotificationStep],
216
354
  })
@@ -116,6 +116,14 @@
116
116
  relationTo: 'automation-steps',
117
117
  required: true
118
118
  },
119
+ {
120
+ name: 'slug',
121
+ type: 'text',
122
+ required: true,
123
+ admin: {
124
+ description: 'Unique identifier for this step within the workflow. Used for dependencies.'
125
+ }
126
+ },
119
127
  {
120
128
  name: 'stepName',
121
129
  type: 'text',
@@ -143,14 +151,14 @@
143
151
  name: 'dependencies',
144
152
  type: 'array',
145
153
  admin: {
146
- description: 'Steps that must complete before this step can run'
154
+ description: 'Steps that must complete before this step can run. Reference steps by their slug.'
147
155
  },
148
156
  fields: [
149
157
  {
150
- name: 'stepIndex',
151
- type: 'number',
158
+ name: 'slug',
159
+ type: 'text',
152
160
  admin: {
153
- description: 'Index of the dependent step (0-based)'
161
+ description: 'Slug of the dependent step'
154
162
  },
155
163
  required: true
156
164
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/collections/Workflow.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\n/**\n * Creates the workflows collection.\n * Workflows reference triggers and steps via relationships for reusability.\n */\nexport const createWorkflowCollection = (): CollectionConfig => {\n return {\n slug: 'workflows',\n access: {\n create: () => true,\n delete: ({ req, data }) => {\n // Prevent deletion of read-only workflows\n if (data?.readOnly === true) {\n return false\n }\n return true\n },\n read: () => true,\n update: ({ req, data }) => {\n // Prevent updates to read-only workflows\n if (data?.readOnly === true) {\n return false\n }\n return true\n },\n },\n admin: {\n defaultColumns: ['name', 'slug', 'readOnly', 'enabled', 'updatedAt'],\n description: 'Create and manage automated workflows.',\n group: 'Automation',\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n admin: {\n description: 'Human-readable name for the workflow',\n },\n required: true,\n },\n {\n name: 'slug',\n type: 'text',\n admin: {\n description: 'URL-safe unique identifier for this workflow',\n position: 'sidebar',\n },\n index: true,\n unique: true,\n },\n {\n name: 'readOnly',\n type: 'checkbox',\n admin: {\n description: 'Read-only workflows cannot be edited or deleted. This is typically used for seeded template workflows.',\n position: 'sidebar',\n readOnly: true,\n },\n defaultValue: false,\n },\n {\n name: 'readOnlyBanner',\n type: 'ui',\n admin: {\n components: {\n Field: '@xtr-dev/payload-automation/client#ReadOnlyBanner',\n },\n condition: (data) => data?.readOnly === true,\n },\n },\n {\n name: 'description',\n type: 'textarea',\n admin: {\n description: 'Optional description of what this workflow does',\n },\n },\n {\n name: 'enabled',\n type: 'checkbox',\n admin: {\n description: 'Enable or disable this workflow',\n position: 'sidebar',\n },\n defaultValue: true,\n },\n // Triggers - relationship to automation-triggers collection\n {\n name: 'triggers',\n type: 'relationship',\n admin: {\n description: 'Triggers that can start this workflow. Uses OR logic - workflow runs if ANY trigger fires.',\n },\n hasMany: true,\n relationTo: 'automation-triggers',\n },\n // Steps with workflow-specific configuration\n {\n name: 'steps',\n type: 'array',\n admin: {\n description: 'Steps to execute when this workflow runs. Steps execute in order based on dependencies.',\n },\n fields: [\n {\n name: 'step',\n type: 'relationship',\n admin: {\n description: 'Select a step from the step library',\n },\n relationTo: 'automation-steps',\n required: true,\n },\n {\n name: 'stepName',\n type: 'text',\n admin: {\n description: 'Override the step name for this workflow instance (optional)',\n },\n },\n {\n name: 'inputOverrides',\n type: 'json',\n admin: {\n description: 'Override step configuration values for this workflow. Merged with step defaults.',\n },\n defaultValue: {},\n },\n {\n name: 'condition',\n type: 'code',\n admin: {\n description: 'JSONata expression that must evaluate to true for this step to execute. Leave empty to always run. Example: trigger.operation = \"create\"',\n language: 'javascript',\n },\n },\n {\n name: 'dependencies',\n type: 'array',\n admin: {\n description: 'Steps that must complete before this step can run',\n },\n fields: [\n {\n name: 'stepIndex',\n type: 'number',\n admin: {\n description: 'Index of the dependent step (0-based)',\n },\n required: true,\n },\n ],\n },\n // Visual builder position\n {\n name: 'position',\n type: 'point',\n admin: {\n description: 'Position in the visual workflow builder',\n hidden: true,\n },\n },\n ],\n },\n // Global workflow settings\n {\n type: 'collapsible',\n label: 'Error Handling',\n admin: {\n initCollapsed: true,\n },\n fields: [\n {\n name: 'errorHandling',\n type: 'select',\n admin: {\n description: 'How to handle step failures',\n },\n defaultValue: 'stop',\n options: [\n { label: 'Stop workflow', value: 'stop' },\n { label: 'Continue to next step', value: 'continue' },\n { label: 'Retry failed step', value: 'retry' },\n ],\n },\n {\n name: 'maxRetries',\n type: 'number',\n admin: {\n condition: (_, siblingData) => siblingData?.errorHandling === 'retry',\n description: 'Maximum number of retry attempts',\n },\n defaultValue: 3,\n },\n {\n name: 'retryDelay',\n type: 'number',\n admin: {\n condition: (_, siblingData) => siblingData?.errorHandling === 'retry',\n description: 'Delay between retries in milliseconds',\n },\n defaultValue: 1000,\n },\n {\n name: 'timeout',\n type: 'number',\n admin: {\n description: 'Maximum execution time in milliseconds (0 for no timeout)',\n },\n defaultValue: 300000, // 5 minutes\n },\n ],\n },\n ],\n hooks: {\n afterChange: [\n // Update usage counts for triggers and steps\n async ({ doc, req }) => {\n const payload = req.payload\n\n // Update trigger usage counts\n if (doc.triggers && Array.isArray(doc.triggers)) {\n for (const triggerId of doc.triggers) {\n const id = typeof triggerId === 'object' ? triggerId.id : triggerId\n if (id) {\n try {\n // Count workflows using this trigger\n const count = await payload.count({\n collection: 'workflows',\n where: {\n triggers: { contains: id },\n },\n })\n await payload.update({\n collection: 'automation-triggers',\n id,\n data: { usageCount: count.totalDocs },\n })\n } catch {\n // Ignore errors - trigger might have been deleted\n }\n }\n }\n }\n\n // Update step usage counts\n if (doc.steps && Array.isArray(doc.steps)) {\n const stepIds = new Set<string>()\n for (const workflowStep of doc.steps) {\n const stepId = typeof workflowStep.step === 'object'\n ? workflowStep.step.id\n : workflowStep.step\n if (stepId) stepIds.add(stepId)\n }\n\n for (const stepId of stepIds) {\n try {\n // Count workflows using this step\n const count = await payload.count({\n collection: 'workflows',\n where: {\n 'steps.step': { equals: stepId },\n },\n })\n await payload.update({\n collection: 'automation-steps',\n id: stepId,\n data: { usageCount: count.totalDocs },\n })\n } catch {\n // Ignore errors - step might have been deleted\n }\n }\n }\n\n return doc\n },\n ],\n },\n versions: {\n drafts: {\n autosave: false,\n },\n maxPerDoc: 10,\n },\n }\n}\n"],"names":["createWorkflowCollection","slug","access","create","delete","req","data","readOnly","read","update","admin","defaultColumns","description","group","useAsTitle","fields","name","type","required","position","index","unique","defaultValue","components","Field","condition","hasMany","relationTo","language","hidden","label","initCollapsed","options","value","_","siblingData","errorHandling","hooks","afterChange","doc","payload","triggers","Array","isArray","triggerId","id","count","collection","where","contains","usageCount","totalDocs","steps","stepIds","Set","workflowStep","stepId","step","add","equals","versions","drafts","autosave","maxPerDoc"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/collections/Workflow.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\n/**\n * Creates the workflows collection.\n * Workflows reference triggers and steps via relationships for reusability.\n */\nexport const createWorkflowCollection = (): CollectionConfig => {\n return {\n slug: 'workflows',\n access: {\n create: () => true,\n delete: ({ req, data }) => {\n // Prevent deletion of read-only workflows\n if (data?.readOnly === true) {\n return false\n }\n return true\n },\n read: () => true,\n update: ({ req, data }) => {\n // Prevent updates to read-only workflows\n if (data?.readOnly === true) {\n return false\n }\n return true\n },\n },\n admin: {\n defaultColumns: ['name', 'slug', 'readOnly', 'enabled', 'updatedAt'],\n description: 'Create and manage automated workflows.',\n group: 'Automation',\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n admin: {\n description: 'Human-readable name for the workflow',\n },\n required: true,\n },\n {\n name: 'slug',\n type: 'text',\n admin: {\n description: 'URL-safe unique identifier for this workflow',\n position: 'sidebar',\n },\n index: true,\n unique: true,\n },\n {\n name: 'readOnly',\n type: 'checkbox',\n admin: {\n description: 'Read-only workflows cannot be edited or deleted. This is typically used for seeded template workflows.',\n position: 'sidebar',\n readOnly: true,\n },\n defaultValue: false,\n },\n {\n name: 'readOnlyBanner',\n type: 'ui',\n admin: {\n components: {\n Field: '@xtr-dev/payload-automation/client#ReadOnlyBanner',\n },\n condition: (data) => data?.readOnly === true,\n },\n },\n {\n name: 'description',\n type: 'textarea',\n admin: {\n description: 'Optional description of what this workflow does',\n },\n },\n {\n name: 'enabled',\n type: 'checkbox',\n admin: {\n description: 'Enable or disable this workflow',\n position: 'sidebar',\n },\n defaultValue: true,\n },\n // Triggers - relationship to automation-triggers collection\n {\n name: 'triggers',\n type: 'relationship',\n admin: {\n description: 'Triggers that can start this workflow. Uses OR logic - workflow runs if ANY trigger fires.',\n },\n hasMany: true,\n relationTo: 'automation-triggers',\n },\n // Steps with workflow-specific configuration\n {\n name: 'steps',\n type: 'array',\n admin: {\n description: 'Steps to execute when this workflow runs. Steps execute in order based on dependencies.',\n },\n fields: [\n {\n name: 'step',\n type: 'relationship',\n admin: {\n description: 'Select a step from the step library',\n },\n relationTo: 'automation-steps',\n required: true,\n },\n {\n name: 'slug',\n type: 'text',\n required: true,\n admin: {\n description: 'Unique identifier for this step within the workflow. Used for dependencies.',\n },\n },\n {\n name: 'stepName',\n type: 'text',\n admin: {\n description: 'Override the step name for this workflow instance (optional)',\n },\n },\n {\n name: 'inputOverrides',\n type: 'json',\n admin: {\n description: 'Override step configuration values for this workflow. Merged with step defaults.',\n },\n defaultValue: {},\n },\n {\n name: 'condition',\n type: 'code',\n admin: {\n description: 'JSONata expression that must evaluate to true for this step to execute. Leave empty to always run. Example: trigger.operation = \"create\"',\n language: 'javascript',\n },\n },\n {\n name: 'dependencies',\n type: 'array',\n admin: {\n description: 'Steps that must complete before this step can run. Reference steps by their slug.',\n },\n fields: [\n {\n name: 'slug',\n type: 'text',\n admin: {\n description: 'Slug of the dependent step',\n },\n required: true,\n },\n ],\n },\n // Visual builder position\n {\n name: 'position',\n type: 'point',\n admin: {\n description: 'Position in the visual workflow builder',\n hidden: true,\n },\n },\n ],\n },\n // Global workflow settings\n {\n type: 'collapsible',\n label: 'Error Handling',\n admin: {\n initCollapsed: true,\n },\n fields: [\n {\n name: 'errorHandling',\n type: 'select',\n admin: {\n description: 'How to handle step failures',\n },\n defaultValue: 'stop',\n options: [\n { label: 'Stop workflow', value: 'stop' },\n { label: 'Continue to next step', value: 'continue' },\n { label: 'Retry failed step', value: 'retry' },\n ],\n },\n {\n name: 'maxRetries',\n type: 'number',\n admin: {\n condition: (_, siblingData) => siblingData?.errorHandling === 'retry',\n description: 'Maximum number of retry attempts',\n },\n defaultValue: 3,\n },\n {\n name: 'retryDelay',\n type: 'number',\n admin: {\n condition: (_, siblingData) => siblingData?.errorHandling === 'retry',\n description: 'Delay between retries in milliseconds',\n },\n defaultValue: 1000,\n },\n {\n name: 'timeout',\n type: 'number',\n admin: {\n description: 'Maximum execution time in milliseconds (0 for no timeout)',\n },\n defaultValue: 300000, // 5 minutes\n },\n ],\n },\n ],\n hooks: {\n afterChange: [\n // Update usage counts for triggers and steps\n async ({ doc, req }) => {\n const payload = req.payload\n\n // Update trigger usage counts\n if (doc.triggers && Array.isArray(doc.triggers)) {\n for (const triggerId of doc.triggers) {\n const id = typeof triggerId === 'object' ? triggerId.id : triggerId\n if (id) {\n try {\n // Count workflows using this trigger\n const count = await payload.count({\n collection: 'workflows',\n where: {\n triggers: { contains: id },\n },\n })\n await payload.update({\n collection: 'automation-triggers',\n id,\n data: { usageCount: count.totalDocs },\n })\n } catch {\n // Ignore errors - trigger might have been deleted\n }\n }\n }\n }\n\n // Update step usage counts\n if (doc.steps && Array.isArray(doc.steps)) {\n const stepIds = new Set<string>()\n for (const workflowStep of doc.steps) {\n const stepId = typeof workflowStep.step === 'object'\n ? workflowStep.step.id\n : workflowStep.step\n if (stepId) stepIds.add(stepId)\n }\n\n for (const stepId of stepIds) {\n try {\n // Count workflows using this step\n const count = await payload.count({\n collection: 'workflows',\n where: {\n 'steps.step': { equals: stepId },\n },\n })\n await payload.update({\n collection: 'automation-steps',\n id: stepId,\n data: { usageCount: count.totalDocs },\n })\n } catch {\n // Ignore errors - step might have been deleted\n }\n }\n }\n\n return doc\n },\n ],\n },\n versions: {\n drafts: {\n autosave: false,\n },\n maxPerDoc: 10,\n },\n }\n}\n"],"names":["createWorkflowCollection","slug","access","create","delete","req","data","readOnly","read","update","admin","defaultColumns","description","group","useAsTitle","fields","name","type","required","position","index","unique","defaultValue","components","Field","condition","hasMany","relationTo","language","hidden","label","initCollapsed","options","value","_","siblingData","errorHandling","hooks","afterChange","doc","payload","triggers","Array","isArray","triggerId","id","count","collection","where","contains","usageCount","totalDocs","steps","stepIds","Set","workflowStep","stepId","step","add","equals","versions","drafts","autosave","maxPerDoc"],"mappings":"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"}
@@ -11,11 +11,12 @@ export type PayloadWorkflow = {
11
11
  steps?: Array<{
12
12
  id?: string;
13
13
  step: any;
14
+ slug: string;
14
15
  stepName?: string | null;
15
16
  inputOverrides?: Record<string, unknown> | null;
16
17
  condition?: string | null;
17
18
  dependencies?: Array<{
18
- stepIndex: number;
19
+ slug: string;
19
20
  }> | null;
20
21
  position?: {
21
22
  x: number;
@@ -33,12 +34,13 @@ export type PayloadWorkflow = {
33
34
  */
34
35
  export type ResolvedStep = {
35
36
  stepIndex: number;
37
+ slug: string;
36
38
  stepId: string | number;
37
39
  stepName: string;
38
40
  stepType: string;
39
41
  config: Record<string, unknown>;
40
42
  condition?: string | null;
41
- dependencies: number[];
43
+ dependencies: string[];
42
44
  retryOnFailure?: boolean;
43
45
  maxRetries?: number;
44
46
  retryDelay?: number;
@@ -49,6 +51,7 @@ export interface ExecutionContext {
49
51
  }
50
52
  export interface StepResult {
51
53
  step?: string | number;
54
+ slug: string;
52
55
  stepName: string;
53
56
  stepIndex: number;
54
57
  status: 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped';
@@ -43,9 +43,10 @@ export class WorkflowExecutor {
43
43
  ...baseConfig,
44
44
  ...overrides
45
45
  };
46
- const dependencies = (workflowStep.dependencies || []).map((d)=>d.stepIndex);
46
+ const dependencies = (workflowStep.dependencies || []).map((d)=>d.slug);
47
47
  resolvedSteps.push({
48
48
  stepIndex: i,
49
+ slug: workflowStep.slug,
49
50
  stepId: baseStep.id,
50
51
  stepName: workflowStep.stepName || baseStep.name || `step-${i}`,
51
52
  stepType: baseStep.type,
@@ -62,17 +63,30 @@ export class WorkflowExecutor {
62
63
  /**
63
64
  * Resolve step execution order based on dependencies
64
65
  */ resolveExecutionOrder(steps) {
66
+ // Create a map from slug to step for lookups
67
+ const stepBySlug = new Map();
68
+ for (const step of steps){
69
+ stepBySlug.set(step.slug, step);
70
+ }
71
+ // Validate all dependencies exist
72
+ for (const step of steps){
73
+ for (const depSlug of step.dependencies){
74
+ if (!stepBySlug.has(depSlug)) {
75
+ throw new Error(`Step "${step.slug}" depends on non-existent step "${depSlug}"`);
76
+ }
77
+ }
78
+ }
65
79
  const indegree = new Map();
66
80
  const dependents = new Map();
67
81
  for (const step of steps){
68
- indegree.set(step.stepIndex, step.dependencies.length);
69
- dependents.set(step.stepIndex, []);
82
+ indegree.set(step.slug, step.dependencies.length);
83
+ dependents.set(step.slug, []);
70
84
  }
71
85
  for (const step of steps){
72
- for (const depIndex of step.dependencies){
73
- const deps = dependents.get(depIndex) || [];
74
- deps.push(step.stepIndex);
75
- dependents.set(depIndex, deps);
86
+ for (const depSlug of step.dependencies){
87
+ const deps = dependents.get(depSlug) || [];
88
+ deps.push(step.slug);
89
+ dependents.set(depSlug, deps);
76
90
  }
77
91
  }
78
92
  const executionBatches = [];
@@ -80,7 +94,7 @@ export class WorkflowExecutor {
80
94
  while(processed.size < steps.length){
81
95
  const currentBatch = [];
82
96
  for (const step of steps){
83
- if (!processed.has(step.stepIndex) && indegree.get(step.stepIndex) === 0) {
97
+ if (!processed.has(step.slug) && indegree.get(step.slug) === 0) {
84
98
  currentBatch.push(step);
85
99
  }
86
100
  }
@@ -89,9 +103,9 @@ export class WorkflowExecutor {
89
103
  }
90
104
  executionBatches.push(currentBatch);
91
105
  for (const step of currentBatch){
92
- processed.add(step.stepIndex);
93
- for (const depIndex of dependents.get(step.stepIndex) || []){
94
- indegree.set(depIndex, (indegree.get(depIndex) || 1) - 1);
106
+ processed.add(step.slug);
107
+ for (const depSlug of dependents.get(step.slug) || []){
108
+ indegree.set(depSlug, (indegree.get(depSlug) || 1) - 1);
95
109
  }
96
110
  }
97
111
  }
@@ -102,6 +116,7 @@ export class WorkflowExecutor {
102
116
  */ async executeStep(step, context, req, stepResults, jobMeta) {
103
117
  const result = {
104
118
  step: step.stepId,
119
+ slug: step.slug,
105
120
  stepName: step.stepName,
106
121
  stepIndex: step.stepIndex,
107
122
  status: 'running',
@@ -349,6 +364,7 @@ export class WorkflowExecutor {
349
364
  for (const step of resolvedSteps){
350
365
  stepResults.push({
351
366
  step: step.stepId,
367
+ slug: step.slug,
352
368
  stepName: step.stepName,
353
369
  stepIndex: step.stepIndex,
354
370
  status: 'pending'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/workflow-executor.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\nimport {\n evaluateCondition as evalCondition,\n resolveStepInput as resolveInput,\n type ExpressionContext\n} from './expression-engine.js'\nimport {getPluginConfig} from \"../plugin/get-plugin-config.js\";\nimport {WorkflowsPluginConfig} from \"../plugin/config-types.js\";\n\n/**\n * Type for workflow data from the refactored collection\n */\nexport type PayloadWorkflow = {\n id: number | string\n name: string\n description?: string | null\n enabled?: boolean\n triggers?: Array<any> | null\n steps?: Array<{\n id?: string\n step: any\n stepName?: string | null\n inputOverrides?: Record<string, unknown> | null\n condition?: string | null\n dependencies?: Array<{ stepIndex: number }> | null\n position?: { x: number; y: number } | null\n }> | null\n errorHandling?: 'stop' | 'continue' | 'retry' | null\n maxRetries?: number | null\n retryDelay?: number | null\n timeout?: number | null\n [key: string]: unknown\n}\n\n/**\n * Type for a resolved workflow step (with base step data merged)\n */\nexport type ResolvedStep = {\n stepIndex: number\n stepId: string | number\n stepName: string\n stepType: string\n config: Record<string, unknown>\n condition?: string | null\n dependencies: number[]\n retryOnFailure?: boolean\n maxRetries?: number\n retryDelay?: number\n}\n\nexport interface ExecutionContext {\n steps: Record<string, any>\n trigger: Record<string, any>\n}\n\nexport interface StepResult {\n step?: string | number\n stepName: string\n stepIndex: number\n status: 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped'\n startedAt?: string\n completedAt?: string\n duration?: number\n input?: Record<string, unknown>\n output?: Record<string, unknown>\n error?: string\n retryCount?: number\n}\n\n/**\n * Workflow context stored on jobs created by workflow execution.\n * Uses relationship IDs that link to the respective collections.\n */\nexport interface WorkflowJobMeta {\n automationWorkflowId: string | number\n automationWorkflowRunId: string | number\n automationTriggerId?: string | number\n}\n\nexport class WorkflowExecutor {\n private config: WorkflowsPluginConfig<string, string>;\n\n constructor(\n private payload: Payload,\n private logger: Payload['logger']\n ) {\n this.config = getPluginConfig(payload)\n }\n\n /**\n * Resolve workflow steps by loading base step configurations and merging with overrides\n */\n private async resolveWorkflowSteps(workflow: PayloadWorkflow): Promise<ResolvedStep[]> {\n const resolvedSteps: ResolvedStep[] = []\n\n if (!workflow.steps || workflow.steps.length === 0) {\n return resolvedSteps\n }\n\n for (let i = 0; i < workflow.steps.length; i++) {\n const workflowStep = workflow.steps[i]\n\n let baseStep: any\n if (typeof workflowStep.step === 'object' && workflowStep.step !== null) {\n baseStep = workflowStep.step\n } else {\n try {\n baseStep = await this.payload.findByID({\n collection: 'automation-steps',\n id: workflowStep.step,\n depth: 0\n })\n } catch (error) {\n this.logger.error({\n stepId: workflowStep.step,\n stepIndex: i,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to load step configuration')\n throw new Error(`Failed to load step ${workflowStep.step}: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n }\n\n const baseConfig = (baseStep.config as Record<string, unknown>) || {}\n const overrides = (workflowStep.inputOverrides as Record<string, unknown>) || {}\n const mergedConfig = { ...baseConfig, ...overrides }\n\n const dependencies = (workflowStep.dependencies || []).map(d => d.stepIndex)\n\n resolvedSteps.push({\n stepIndex: i,\n stepId: baseStep.id,\n stepName: workflowStep.stepName || baseStep.name || `step-${i}`,\n stepType: baseStep.type as string,\n config: mergedConfig,\n condition: workflowStep.condition,\n dependencies,\n retryOnFailure: baseStep.retryOnFailure,\n maxRetries: baseStep.maxRetries || workflow.maxRetries || 3,\n retryDelay: baseStep.retryDelay || workflow.retryDelay || 1000\n })\n }\n\n return resolvedSteps\n }\n\n /**\n * Resolve step execution order based on dependencies\n */\n private resolveExecutionOrder(steps: ResolvedStep[]): ResolvedStep[][] {\n const indegree = new Map<number, number>()\n const dependents = new Map<number, number[]>()\n\n for (const step of steps) {\n indegree.set(step.stepIndex, step.dependencies.length)\n dependents.set(step.stepIndex, [])\n }\n\n for (const step of steps) {\n for (const depIndex of step.dependencies) {\n const deps = dependents.get(depIndex) || []\n deps.push(step.stepIndex)\n dependents.set(depIndex, deps)\n }\n }\n\n const executionBatches: ResolvedStep[][] = []\n const processed = new Set<number>()\n\n while (processed.size < steps.length) {\n const currentBatch: ResolvedStep[] = []\n\n for (const step of steps) {\n if (!processed.has(step.stepIndex) && indegree.get(step.stepIndex) === 0) {\n currentBatch.push(step)\n }\n }\n\n if (currentBatch.length === 0) {\n throw new Error('Circular dependency detected in workflow steps')\n }\n\n executionBatches.push(currentBatch)\n\n for (const step of currentBatch) {\n processed.add(step.stepIndex)\n for (const depIndex of dependents.get(step.stepIndex) || []) {\n indegree.set(depIndex, (indegree.get(depIndex) || 1) - 1)\n }\n }\n }\n\n return executionBatches\n }\n\n /**\n * Execute a single workflow step\n */\n private async executeStep(\n step: ResolvedStep,\n context: ExecutionContext,\n req: PayloadRequest,\n stepResults: StepResult[],\n jobMeta: WorkflowJobMeta\n ): Promise<StepResult> {\n const result: StepResult = {\n step: step.stepId,\n stepName: step.stepName,\n stepIndex: step.stepIndex,\n status: 'running',\n startedAt: new Date().toISOString(),\n retryCount: 0\n }\n\n this.logger.info({\n stepName: step.stepName,\n stepType: step.stepType,\n stepIndex: step.stepIndex\n }, 'Executing step')\n\n // Check step condition if present\n if (step.condition) {\n const conditionMet = await this.evaluateCondition(step.condition, context)\n if (!conditionMet) {\n this.logger.info({\n stepName: step.stepName,\n condition: step.condition\n }, 'Step condition not met, skipping')\n\n result.status = 'skipped'\n result.completedAt = new Date().toISOString()\n result.output = { reason: 'Condition not met', skipped: true }\n\n context.steps[step.stepName] = {\n state: 'skipped',\n output: result.output\n }\n\n return result\n }\n }\n\n // Resolve input using JSONata expressions\n const resolvedInput = await this.resolveStepInput(step.config, context)\n result.input = resolvedInput\n\n context.steps[step.stepName] = {\n state: 'running',\n input: resolvedInput\n }\n\n try {\n const job = await this.payload.jobs.queue({\n input: resolvedInput,\n req,\n task: step.stepType,\n })\n\n if (this.config.debug) {\n this.logger.info(job, `Queued job for step '${step.stepName}'`)\n }\n\n // Update the job with automation context fields\n // This allows tracking which workflow run triggered this job\n await this.payload.update({\n collection: 'payload-jobs',\n id: job.id,\n data: {\n automationWorkflow: jobMeta.automationWorkflowId,\n automationWorkflowRun: jobMeta.automationWorkflowRunId,\n automationTrigger: jobMeta.automationTriggerId,\n automationStepName: step.stepName,\n },\n req,\n })\n\n // Run the job and capture the result directly from runByID\n // This is important because PayloadCMS may delete jobs on completion (deleteJobOnComplete: true by default)\n const runResult = await this.payload.jobs.runByID({\n id: job.id,\n req\n })\n\n if (this.config.debug) {\n this.logger.info(runResult, `Run result for step '${step.stepName}'`)\n }\n\n // Check the job status from the run result\n // runByID returns { jobStatus: { [jobId]: { status: 'success' | 'error' | ... } }, ... }\n const jobStatus = (runResult as any)?.jobStatus?.[job.id]\n const jobSucceeded = jobStatus?.status === 'success'\n\n if (jobSucceeded) {\n // Job completed successfully - try to get output from the job if it still exists\n // Note: Job may have been deleted if deleteJobOnComplete is true\n let output: Record<string, unknown> = {}\n try {\n const completedJob = await this.payload.findByID({\n id: job.id,\n collection: 'payload-jobs',\n req\n })\n const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried]\n output = taskStatus?.output || {}\n } catch {\n // Job was deleted after completion - this is expected behavior with deleteJobOnComplete: true\n // The job succeeded, so we proceed without the output\n this.logger.debug({ stepName: step.stepName }, 'Job was deleted after successful completion (deleteJobOnComplete)')\n }\n\n result.status = 'succeeded'\n result.output = output\n result.completedAt = new Date().toISOString()\n result.duration = new Date(result.completedAt).getTime() - new Date(result.startedAt!).getTime()\n } else {\n // Job failed - try to get error details from the job\n let errorMessage = 'Task failed'\n try {\n const completedJob = await this.payload.findByID({\n id: job.id,\n collection: 'payload-jobs',\n req\n })\n const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried]\n if (completedJob.log && completedJob.log.length > 0) {\n const latestLog = completedJob.log[completedJob.log.length - 1]\n errorMessage = latestLog.error?.message || latestLog.error || errorMessage\n }\n if (taskStatus?.output?.errorMessage) {\n errorMessage = taskStatus.output.errorMessage\n }\n } catch {\n // Job may have been deleted - use the job status from run result\n errorMessage = `Task failed with status: ${jobStatus?.status || 'unknown'}`\n }\n throw new Error(errorMessage)\n }\n\n context.steps[step.stepName] = {\n state: 'succeeded',\n input: resolvedInput,\n output: result.output\n }\n\n this.logger.info({\n stepName: step.stepName,\n duration: result.duration\n }, 'Step completed successfully')\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n result.status = 'failed'\n result.error = errorMessage\n result.completedAt = new Date().toISOString()\n result.duration = new Date(result.completedAt).getTime() - new Date(result.startedAt!).getTime()\n\n context.steps[step.stepName] = {\n state: 'failed',\n input: resolvedInput,\n error: errorMessage\n }\n\n this.logger.error({\n stepName: step.stepName,\n error: errorMessage\n }, 'Step execution failed')\n\n throw error\n }\n\n return result\n }\n\n /**\n * Resolve step input using JSONata expressions\n */\n private async resolveStepInput(\n config: Record<string, unknown>,\n context: ExecutionContext\n ): Promise<Record<string, unknown>> {\n try {\n return await resolveInput(config, context as ExpressionContext, {\n timeout: 5000,\n debug: this.config.debug,\n logger: this.logger\n })\n } catch (error) {\n this.logger.warn({\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to resolve step input, using raw config')\n return config\n }\n }\n\n /**\n * Evaluate a condition using JSONata\n */\n public async evaluateCondition(condition: string, context: ExecutionContext): Promise<boolean> {\n try {\n return await evalCondition(condition, context as ExpressionContext, { timeout: 5000 })\n } catch (error) {\n this.logger.warn({\n condition,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to evaluate condition')\n return false\n }\n }\n\n /**\n * Safely serialize an object for storage\n */\n private safeSerialize(obj: unknown): unknown {\n const seen = new WeakSet()\n\n // Keys to completely exclude from serialization\n const excludeKeys = new Set([\n 'table',\n 'schema',\n '_',\n '__',\n 'payload', // Exclude payload instance (contains entire config)\n 'res', // Exclude response object\n 'transactionID',\n 'i18n',\n 'fallbackLocale',\n ])\n\n // For req object, only keep these useful debugging properties\n const reqAllowedKeys = new Set([\n 'payloadAPI', // 'local', 'REST', or 'GraphQL'\n 'locale',\n 'user', // authenticated user\n 'method', // HTTP method\n 'url', // request URL\n ])\n\n const serialize = (value: unknown, parentKey?: string): unknown => {\n if (value === null || typeof value !== 'object') {\n return value\n }\n if (seen.has(value)) {\n return '[Circular Reference]'\n }\n seen.add(value)\n\n if (Array.isArray(value)) {\n return value.map((v) => serialize(v))\n }\n\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n try {\n if (excludeKeys.has(key)) {\n continue\n }\n // Special handling for req object - only include allowed keys\n if (parentKey === 'req' && !reqAllowedKeys.has(key)) {\n continue\n }\n result[key] = serialize(val, key)\n } catch {\n result[key] = '[Non-serializable]'\n }\n }\n return result\n }\n\n return serialize(obj)\n }\n\n /**\n * Execute a workflow with the given context\n */\n async execute(\n workflow: PayloadWorkflow,\n context: ExecutionContext,\n req: PayloadRequest,\n firedTrigger?: any\n ): Promise<void> {\n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name,\n triggerId: firedTrigger?.id,\n triggerName: firedTrigger?.name\n }, 'Starting workflow execution')\n\n const resolvedSteps = await this.resolveWorkflowSteps(workflow)\n const stepResults: StepResult[] = []\n\n for (const step of resolvedSteps) {\n stepResults.push({\n step: step.stepId,\n stepName: step.stepName,\n stepIndex: step.stepIndex,\n status: 'pending'\n })\n }\n\n const workflowRun = await this.payload.create({\n collection: 'workflow-runs',\n data: {\n workflow: workflow.id,\n workflowVersion: 1,\n firedTrigger: firedTrigger?.id,\n triggerData: this.safeSerialize(context.trigger),\n status: 'running',\n startedAt: new Date().toISOString(),\n triggeredBy: context.trigger.req?.user?.email || 'system',\n stepResults,\n context: this.safeSerialize(context),\n inputs: this.safeSerialize(context.trigger),\n logs: [{\n timestamp: new Date().toISOString(),\n level: 'info',\n message: 'Workflow execution started'\n }]\n },\n req\n })\n\n this.logger.info({\n workflowRunId: workflowRun.id,\n workflowId: workflow.id\n }, 'Workflow run record created')\n\n // Create job metadata for tracking workflow context in payload-jobs\n const jobMeta: WorkflowJobMeta = {\n automationWorkflowId: workflow.id,\n automationWorkflowRunId: workflowRun.id,\n automationTriggerId: firedTrigger?.id,\n }\n\n try {\n const executionBatches = this.resolveExecutionOrder(resolvedSteps)\n\n this.logger.info({\n batchCount: executionBatches.length,\n batchSizes: executionBatches.map(b => b.length)\n }, 'Resolved step execution order')\n\n for (let batchIndex = 0; batchIndex < executionBatches.length; batchIndex++) {\n const batch = executionBatches[batchIndex]\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length,\n stepNames: batch.map(s => s.stepName)\n }, 'Executing batch')\n\n const batchPromises = batch.map(async (step) => {\n try {\n const result = await this.executeStep(step, context, req, stepResults, jobMeta)\n const idx = stepResults.findIndex(r => r.stepIndex === step.stepIndex)\n if (idx !== -1) {\n stepResults[idx] = result\n }\n return result\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n const idx = stepResults.findIndex(r => r.stepIndex === step.stepIndex)\n if (idx !== -1) {\n stepResults[idx] = {\n ...stepResults[idx],\n status: 'failed',\n error: errorMessage,\n completedAt: new Date().toISOString()\n }\n }\n\n if (workflow.errorHandling === 'stop') {\n throw error\n }\n this.logger.warn({\n stepName: step.stepName,\n error: errorMessage\n }, 'Step failed but continuing due to error handling setting')\n }\n })\n\n await Promise.all(batchPromises)\n\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n stepResults,\n context: this.safeSerialize(context)\n },\n req\n })\n }\n\n const outputs: Record<string, unknown> = {}\n for (const result of stepResults) {\n if (result.status === 'succeeded' && result.output) {\n outputs[result.stepName] = result.output\n }\n }\n\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n status: 'completed',\n completedAt: new Date().toISOString(),\n stepResults,\n context: this.safeSerialize(context),\n outputs,\n logs: [\n ...(workflowRun.logs || []),\n {\n timestamp: new Date().toISOString(),\n level: 'info',\n message: 'Workflow execution completed successfully'\n }\n ]\n },\n req\n })\n\n this.logger.info({\n workflowRunId: workflowRun.id,\n workflowId: workflow.id\n }, 'Workflow execution completed')\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n status: 'failed',\n completedAt: new Date().toISOString(),\n stepResults,\n context: this.safeSerialize(context),\n error: errorMessage,\n logs: [\n ...(workflowRun.logs || []),\n {\n timestamp: new Date().toISOString(),\n level: 'error',\n message: `Workflow execution failed: ${errorMessage}`\n }\n ]\n },\n req\n })\n\n this.logger.error({\n workflowRunId: workflowRun.id,\n workflowId: workflow.id,\n error: errorMessage\n }, 'Workflow execution failed')\n\n throw error\n }\n }\n}\n"],"names":["evaluateCondition","evalCondition","resolveStepInput","resolveInput","getPluginConfig","WorkflowExecutor","config","payload","logger","resolveWorkflowSteps","workflow","resolvedSteps","steps","length","i","workflowStep","baseStep","step","findByID","collection","id","depth","error","stepId","stepIndex","Error","message","baseConfig","overrides","inputOverrides","mergedConfig","dependencies","map","d","push","stepName","name","stepType","type","condition","retryOnFailure","maxRetries","retryDelay","resolveExecutionOrder","indegree","Map","dependents","set","depIndex","deps","get","executionBatches","processed","Set","size","currentBatch","has","add","executeStep","context","req","stepResults","jobMeta","result","status","startedAt","Date","toISOString","retryCount","info","conditionMet","completedAt","output","reason","skipped","state","resolvedInput","input","job","jobs","queue","task","debug","update","data","automationWorkflow","automationWorkflowId","automationWorkflowRun","automationWorkflowRunId","automationTrigger","automationTriggerId","automationStepName","runResult","runByID","jobStatus","jobSucceeded","completedJob","taskStatus","taskSlug","totalTried","duration","getTime","errorMessage","log","latestLog","timeout","warn","safeSerialize","obj","seen","WeakSet","excludeKeys","reqAllowedKeys","serialize","value","parentKey","Array","isArray","v","key","val","Object","entries","execute","firedTrigger","workflowId","workflowName","triggerId","triggerName","workflowRun","create","workflowVersion","triggerData","trigger","triggeredBy","user","email","inputs","logs","timestamp","level","workflowRunId","batchCount","batchSizes","b","batchIndex","batch","stepCount","stepNames","s","batchPromises","idx","findIndex","r","errorHandling","Promise","all","outputs"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/workflow-executor.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\nimport {\n evaluateCondition as evalCondition,\n resolveStepInput as resolveInput,\n type ExpressionContext\n} from './expression-engine.js'\nimport {getPluginConfig} from \"../plugin/get-plugin-config.js\";\nimport {WorkflowsPluginConfig} from \"../plugin/config-types.js\";\n\n/**\n * Type for workflow data from the refactored collection\n */\nexport type PayloadWorkflow = {\n id: number | string\n name: string\n description?: string | null\n enabled?: boolean\n triggers?: Array<any> | null\n steps?: Array<{\n id?: string\n step: any\n slug: string\n stepName?: string | null\n inputOverrides?: Record<string, unknown> | null\n condition?: string | null\n dependencies?: Array<{ slug: string }> | null\n position?: { x: number; y: number } | null\n }> | null\n errorHandling?: 'stop' | 'continue' | 'retry' | null\n maxRetries?: number | null\n retryDelay?: number | null\n timeout?: number | null\n [key: string]: unknown\n}\n\n/**\n * Type for a resolved workflow step (with base step data merged)\n */\nexport type ResolvedStep = {\n stepIndex: number\n slug: string\n stepId: string | number\n stepName: string\n stepType: string\n config: Record<string, unknown>\n condition?: string | null\n dependencies: string[]\n retryOnFailure?: boolean\n maxRetries?: number\n retryDelay?: number\n}\n\nexport interface ExecutionContext {\n steps: Record<string, any>\n trigger: Record<string, any>\n}\n\nexport interface StepResult {\n step?: string | number\n slug: string\n stepName: string\n stepIndex: number\n status: 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped'\n startedAt?: string\n completedAt?: string\n duration?: number\n input?: Record<string, unknown>\n output?: Record<string, unknown>\n error?: string\n retryCount?: number\n}\n\n/**\n * Workflow context stored on jobs created by workflow execution.\n * Uses relationship IDs that link to the respective collections.\n */\nexport interface WorkflowJobMeta {\n automationWorkflowId: string | number\n automationWorkflowRunId: string | number\n automationTriggerId?: string | number\n}\n\nexport class WorkflowExecutor {\n private config: WorkflowsPluginConfig<string, string>;\n\n constructor(\n private payload: Payload,\n private logger: Payload['logger']\n ) {\n this.config = getPluginConfig(payload)\n }\n\n /**\n * Resolve workflow steps by loading base step configurations and merging with overrides\n */\n private async resolveWorkflowSteps(workflow: PayloadWorkflow): Promise<ResolvedStep[]> {\n const resolvedSteps: ResolvedStep[] = []\n\n if (!workflow.steps || workflow.steps.length === 0) {\n return resolvedSteps\n }\n\n for (let i = 0; i < workflow.steps.length; i++) {\n const workflowStep = workflow.steps[i]\n\n let baseStep: any\n if (typeof workflowStep.step === 'object' && workflowStep.step !== null) {\n baseStep = workflowStep.step\n } else {\n try {\n baseStep = await this.payload.findByID({\n collection: 'automation-steps',\n id: workflowStep.step,\n depth: 0\n })\n } catch (error) {\n this.logger.error({\n stepId: workflowStep.step,\n stepIndex: i,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to load step configuration')\n throw new Error(`Failed to load step ${workflowStep.step}: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n }\n\n const baseConfig = (baseStep.config as Record<string, unknown>) || {}\n const overrides = (workflowStep.inputOverrides as Record<string, unknown>) || {}\n const mergedConfig = { ...baseConfig, ...overrides }\n\n const dependencies = (workflowStep.dependencies || []).map(d => d.slug)\n\n resolvedSteps.push({\n stepIndex: i,\n slug: workflowStep.slug,\n stepId: baseStep.id,\n stepName: workflowStep.stepName || baseStep.name || `step-${i}`,\n stepType: baseStep.type as string,\n config: mergedConfig,\n condition: workflowStep.condition,\n dependencies,\n retryOnFailure: baseStep.retryOnFailure,\n maxRetries: baseStep.maxRetries || workflow.maxRetries || 3,\n retryDelay: baseStep.retryDelay || workflow.retryDelay || 1000\n })\n }\n\n return resolvedSteps\n }\n\n /**\n * Resolve step execution order based on dependencies\n */\n private resolveExecutionOrder(steps: ResolvedStep[]): ResolvedStep[][] {\n // Create a map from slug to step for lookups\n const stepBySlug = new Map<string, ResolvedStep>()\n for (const step of steps) {\n stepBySlug.set(step.slug, step)\n }\n\n // Validate all dependencies exist\n for (const step of steps) {\n for (const depSlug of step.dependencies) {\n if (!stepBySlug.has(depSlug)) {\n throw new Error(`Step \"${step.slug}\" depends on non-existent step \"${depSlug}\"`)\n }\n }\n }\n\n const indegree = new Map<string, number>()\n const dependents = new Map<string, string[]>()\n\n for (const step of steps) {\n indegree.set(step.slug, step.dependencies.length)\n dependents.set(step.slug, [])\n }\n\n for (const step of steps) {\n for (const depSlug of step.dependencies) {\n const deps = dependents.get(depSlug) || []\n deps.push(step.slug)\n dependents.set(depSlug, deps)\n }\n }\n\n const executionBatches: ResolvedStep[][] = []\n const processed = new Set<string>()\n\n while (processed.size < steps.length) {\n const currentBatch: ResolvedStep[] = []\n\n for (const step of steps) {\n if (!processed.has(step.slug) && indegree.get(step.slug) === 0) {\n currentBatch.push(step)\n }\n }\n\n if (currentBatch.length === 0) {\n throw new Error('Circular dependency detected in workflow steps')\n }\n\n executionBatches.push(currentBatch)\n\n for (const step of currentBatch) {\n processed.add(step.slug)\n for (const depSlug of dependents.get(step.slug) || []) {\n indegree.set(depSlug, (indegree.get(depSlug) || 1) - 1)\n }\n }\n }\n\n return executionBatches\n }\n\n /**\n * Execute a single workflow step\n */\n private async executeStep(\n step: ResolvedStep,\n context: ExecutionContext,\n req: PayloadRequest,\n stepResults: StepResult[],\n jobMeta: WorkflowJobMeta\n ): Promise<StepResult> {\n const result: StepResult = {\n step: step.stepId,\n slug: step.slug,\n stepName: step.stepName,\n stepIndex: step.stepIndex,\n status: 'running',\n startedAt: new Date().toISOString(),\n retryCount: 0\n }\n\n this.logger.info({\n stepName: step.stepName,\n stepType: step.stepType,\n stepIndex: step.stepIndex\n }, 'Executing step')\n\n // Check step condition if present\n if (step.condition) {\n const conditionMet = await this.evaluateCondition(step.condition, context)\n if (!conditionMet) {\n this.logger.info({\n stepName: step.stepName,\n condition: step.condition\n }, 'Step condition not met, skipping')\n\n result.status = 'skipped'\n result.completedAt = new Date().toISOString()\n result.output = { reason: 'Condition not met', skipped: true }\n\n context.steps[step.stepName] = {\n state: 'skipped',\n output: result.output\n }\n\n return result\n }\n }\n\n // Resolve input using JSONata expressions\n const resolvedInput = await this.resolveStepInput(step.config, context)\n result.input = resolvedInput\n\n context.steps[step.stepName] = {\n state: 'running',\n input: resolvedInput\n }\n\n try {\n const job = await this.payload.jobs.queue({\n input: resolvedInput,\n req,\n task: step.stepType,\n })\n\n if (this.config.debug) {\n this.logger.info(job, `Queued job for step '${step.stepName}'`)\n }\n\n // Update the job with automation context fields\n // This allows tracking which workflow run triggered this job\n await this.payload.update({\n collection: 'payload-jobs',\n id: job.id,\n data: {\n automationWorkflow: jobMeta.automationWorkflowId,\n automationWorkflowRun: jobMeta.automationWorkflowRunId,\n automationTrigger: jobMeta.automationTriggerId,\n automationStepName: step.stepName,\n },\n req,\n })\n\n // Run the job and capture the result directly from runByID\n // This is important because PayloadCMS may delete jobs on completion (deleteJobOnComplete: true by default)\n const runResult = await this.payload.jobs.runByID({\n id: job.id,\n req\n })\n\n if (this.config.debug) {\n this.logger.info(runResult, `Run result for step '${step.stepName}'`)\n }\n\n // Check the job status from the run result\n // runByID returns { jobStatus: { [jobId]: { status: 'success' | 'error' | ... } }, ... }\n const jobStatus = (runResult as any)?.jobStatus?.[job.id]\n const jobSucceeded = jobStatus?.status === 'success'\n\n if (jobSucceeded) {\n // Job completed successfully - try to get output from the job if it still exists\n // Note: Job may have been deleted if deleteJobOnComplete is true\n let output: Record<string, unknown> = {}\n try {\n const completedJob = await this.payload.findByID({\n id: job.id,\n collection: 'payload-jobs',\n req\n })\n const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried]\n output = taskStatus?.output || {}\n } catch {\n // Job was deleted after completion - this is expected behavior with deleteJobOnComplete: true\n // The job succeeded, so we proceed without the output\n this.logger.debug({ stepName: step.stepName }, 'Job was deleted after successful completion (deleteJobOnComplete)')\n }\n\n result.status = 'succeeded'\n result.output = output\n result.completedAt = new Date().toISOString()\n result.duration = new Date(result.completedAt).getTime() - new Date(result.startedAt!).getTime()\n } else {\n // Job failed - try to get error details from the job\n let errorMessage = 'Task failed'\n try {\n const completedJob = await this.payload.findByID({\n id: job.id,\n collection: 'payload-jobs',\n req\n })\n const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried]\n if (completedJob.log && completedJob.log.length > 0) {\n const latestLog = completedJob.log[completedJob.log.length - 1]\n errorMessage = latestLog.error?.message || latestLog.error || errorMessage\n }\n if (taskStatus?.output?.errorMessage) {\n errorMessage = taskStatus.output.errorMessage\n }\n } catch {\n // Job may have been deleted - use the job status from run result\n errorMessage = `Task failed with status: ${jobStatus?.status || 'unknown'}`\n }\n throw new Error(errorMessage)\n }\n\n context.steps[step.stepName] = {\n state: 'succeeded',\n input: resolvedInput,\n output: result.output\n }\n\n this.logger.info({\n stepName: step.stepName,\n duration: result.duration\n }, 'Step completed successfully')\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n result.status = 'failed'\n result.error = errorMessage\n result.completedAt = new Date().toISOString()\n result.duration = new Date(result.completedAt).getTime() - new Date(result.startedAt!).getTime()\n\n context.steps[step.stepName] = {\n state: 'failed',\n input: resolvedInput,\n error: errorMessage\n }\n\n this.logger.error({\n stepName: step.stepName,\n error: errorMessage\n }, 'Step execution failed')\n\n throw error\n }\n\n return result\n }\n\n /**\n * Resolve step input using JSONata expressions\n */\n private async resolveStepInput(\n config: Record<string, unknown>,\n context: ExecutionContext\n ): Promise<Record<string, unknown>> {\n try {\n return await resolveInput(config, context as ExpressionContext, {\n timeout: 5000,\n debug: this.config.debug,\n logger: this.logger\n })\n } catch (error) {\n this.logger.warn({\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to resolve step input, using raw config')\n return config\n }\n }\n\n /**\n * Evaluate a condition using JSONata\n */\n public async evaluateCondition(condition: string, context: ExecutionContext): Promise<boolean> {\n try {\n return await evalCondition(condition, context as ExpressionContext, { timeout: 5000 })\n } catch (error) {\n this.logger.warn({\n condition,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to evaluate condition')\n return false\n }\n }\n\n /**\n * Safely serialize an object for storage\n */\n private safeSerialize(obj: unknown): unknown {\n const seen = new WeakSet()\n\n // Keys to completely exclude from serialization\n const excludeKeys = new Set([\n 'table',\n 'schema',\n '_',\n '__',\n 'payload', // Exclude payload instance (contains entire config)\n 'res', // Exclude response object\n 'transactionID',\n 'i18n',\n 'fallbackLocale',\n ])\n\n // For req object, only keep these useful debugging properties\n const reqAllowedKeys = new Set([\n 'payloadAPI', // 'local', 'REST', or 'GraphQL'\n 'locale',\n 'user', // authenticated user\n 'method', // HTTP method\n 'url', // request URL\n ])\n\n const serialize = (value: unknown, parentKey?: string): unknown => {\n if (value === null || typeof value !== 'object') {\n return value\n }\n if (seen.has(value)) {\n return '[Circular Reference]'\n }\n seen.add(value)\n\n if (Array.isArray(value)) {\n return value.map((v) => serialize(v))\n }\n\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n try {\n if (excludeKeys.has(key)) {\n continue\n }\n // Special handling for req object - only include allowed keys\n if (parentKey === 'req' && !reqAllowedKeys.has(key)) {\n continue\n }\n result[key] = serialize(val, key)\n } catch {\n result[key] = '[Non-serializable]'\n }\n }\n return result\n }\n\n return serialize(obj)\n }\n\n /**\n * Execute a workflow with the given context\n */\n async execute(\n workflow: PayloadWorkflow,\n context: ExecutionContext,\n req: PayloadRequest,\n firedTrigger?: any\n ): Promise<void> {\n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name,\n triggerId: firedTrigger?.id,\n triggerName: firedTrigger?.name\n }, 'Starting workflow execution')\n\n const resolvedSteps = await this.resolveWorkflowSteps(workflow)\n const stepResults: StepResult[] = []\n\n for (const step of resolvedSteps) {\n stepResults.push({\n step: step.stepId,\n slug: step.slug,\n stepName: step.stepName,\n stepIndex: step.stepIndex,\n status: 'pending'\n })\n }\n\n const workflowRun = await this.payload.create({\n collection: 'workflow-runs',\n data: {\n workflow: workflow.id,\n workflowVersion: 1,\n firedTrigger: firedTrigger?.id,\n triggerData: this.safeSerialize(context.trigger),\n status: 'running',\n startedAt: new Date().toISOString(),\n triggeredBy: context.trigger.req?.user?.email || 'system',\n stepResults,\n context: this.safeSerialize(context),\n inputs: this.safeSerialize(context.trigger),\n logs: [{\n timestamp: new Date().toISOString(),\n level: 'info',\n message: 'Workflow execution started'\n }]\n },\n req\n })\n\n this.logger.info({\n workflowRunId: workflowRun.id,\n workflowId: workflow.id\n }, 'Workflow run record created')\n\n // Create job metadata for tracking workflow context in payload-jobs\n const jobMeta: WorkflowJobMeta = {\n automationWorkflowId: workflow.id,\n automationWorkflowRunId: workflowRun.id,\n automationTriggerId: firedTrigger?.id,\n }\n\n try {\n const executionBatches = this.resolveExecutionOrder(resolvedSteps)\n\n this.logger.info({\n batchCount: executionBatches.length,\n batchSizes: executionBatches.map(b => b.length)\n }, 'Resolved step execution order')\n\n for (let batchIndex = 0; batchIndex < executionBatches.length; batchIndex++) {\n const batch = executionBatches[batchIndex]\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length,\n stepNames: batch.map(s => s.stepName)\n }, 'Executing batch')\n\n const batchPromises = batch.map(async (step) => {\n try {\n const result = await this.executeStep(step, context, req, stepResults, jobMeta)\n const idx = stepResults.findIndex(r => r.stepIndex === step.stepIndex)\n if (idx !== -1) {\n stepResults[idx] = result\n }\n return result\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n const idx = stepResults.findIndex(r => r.stepIndex === step.stepIndex)\n if (idx !== -1) {\n stepResults[idx] = {\n ...stepResults[idx],\n status: 'failed',\n error: errorMessage,\n completedAt: new Date().toISOString()\n }\n }\n\n if (workflow.errorHandling === 'stop') {\n throw error\n }\n this.logger.warn({\n stepName: step.stepName,\n error: errorMessage\n }, 'Step failed but continuing due to error handling setting')\n }\n })\n\n await Promise.all(batchPromises)\n\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n stepResults,\n context: this.safeSerialize(context)\n },\n req\n })\n }\n\n const outputs: Record<string, unknown> = {}\n for (const result of stepResults) {\n if (result.status === 'succeeded' && result.output) {\n outputs[result.stepName] = result.output\n }\n }\n\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n status: 'completed',\n completedAt: new Date().toISOString(),\n stepResults,\n context: this.safeSerialize(context),\n outputs,\n logs: [\n ...(workflowRun.logs || []),\n {\n timestamp: new Date().toISOString(),\n level: 'info',\n message: 'Workflow execution completed successfully'\n }\n ]\n },\n req\n })\n\n this.logger.info({\n workflowRunId: workflowRun.id,\n workflowId: workflow.id\n }, 'Workflow execution completed')\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n status: 'failed',\n completedAt: new Date().toISOString(),\n stepResults,\n context: this.safeSerialize(context),\n error: errorMessage,\n logs: [\n ...(workflowRun.logs || []),\n {\n timestamp: new Date().toISOString(),\n level: 'error',\n message: `Workflow execution failed: ${errorMessage}`\n }\n ]\n },\n req\n })\n\n this.logger.error({\n workflowRunId: workflowRun.id,\n workflowId: workflow.id,\n error: errorMessage\n }, 'Workflow execution failed')\n\n throw error\n }\n }\n}\n"],"names":["evaluateCondition","evalCondition","resolveStepInput","resolveInput","getPluginConfig","WorkflowExecutor","config","payload","logger","resolveWorkflowSteps","workflow","resolvedSteps","steps","length","i","workflowStep","baseStep","step","findByID","collection","id","depth","error","stepId","stepIndex","Error","message","baseConfig","overrides","inputOverrides","mergedConfig","dependencies","map","d","slug","push","stepName","name","stepType","type","condition","retryOnFailure","maxRetries","retryDelay","resolveExecutionOrder","stepBySlug","Map","set","depSlug","has","indegree","dependents","deps","get","executionBatches","processed","Set","size","currentBatch","add","executeStep","context","req","stepResults","jobMeta","result","status","startedAt","Date","toISOString","retryCount","info","conditionMet","completedAt","output","reason","skipped","state","resolvedInput","input","job","jobs","queue","task","debug","update","data","automationWorkflow","automationWorkflowId","automationWorkflowRun","automationWorkflowRunId","automationTrigger","automationTriggerId","automationStepName","runResult","runByID","jobStatus","jobSucceeded","completedJob","taskStatus","taskSlug","totalTried","duration","getTime","errorMessage","log","latestLog","timeout","warn","safeSerialize","obj","seen","WeakSet","excludeKeys","reqAllowedKeys","serialize","value","parentKey","Array","isArray","v","key","val","Object","entries","execute","firedTrigger","workflowId","workflowName","triggerId","triggerName","workflowRun","create","workflowVersion","triggerData","trigger","triggeredBy","user","email","inputs","logs","timestamp","level","workflowRunId","batchCount","batchSizes","b","batchIndex","batch","stepCount","stepNames","s","batchPromises","idx","findIndex","r","errorHandling","Promise","all","outputs"],"mappings":"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"}
@@ -23,6 +23,7 @@ export type SeedWorkflow = {
23
23
  }>;
24
24
  steps: Array<{
25
25
  name: string;
26
+ slug?: string;
26
27
  type: string;
27
28
  input?: Record<string, any>;
28
29
  dependencies?: string[];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugin/config-types.ts"],"sourcesContent":["import type {CollectionConfig, GlobalConfig, TaskConfig} from \"payload\"\n\n/**\n * Trigger definition for custom trigger configurations.\n */\nexport interface Trigger {\n slug: string\n label?: string\n parameters?: Array<{\n name: string\n type: string\n required?: boolean\n }>\n}\n\nexport type TriggerConfig = (config: WorkflowsPluginConfig) => Trigger\n\nexport type SeedWorkflow = {\n slug: string\n name: string\n description?: string\n triggers: Array<{\n type: string\n parameters?: Record<string, any>\n condition?: string\n }>\n steps: Array<{\n name: string\n type: string\n input?: Record<string, any>\n dependencies?: string[]\n condition?: string\n }>\n}\n\n/**\n * Plugin configuration for the workflows automation plugin.\n */\nexport type WorkflowsPluginConfig<\n TCollection extends string = string,\n TGlobal extends string = string\n> = {\n /**\n * Whether the plugin is enabled. Defaults to true.\n */\n enabled?: boolean\n\n /**\n * Collection triggers configuration.\n * Keys are collection slugs, values configure which hooks to listen to.\n * Set to `true` to enable all default hooks (afterChange, afterDelete, afterRead).\n */\n collectionTriggers?: {\n [key in TCollection]?: {\n [key in keyof CollectionConfig['hooks']]?: true\n } | true\n }\n\n /**\n * Global triggers configuration.\n * Keys are global slugs, values configure which hooks to listen to.\n * Set to `true` to enable all default hooks (afterChange, afterRead).\n */\n globalTriggers?: {\n [key in TGlobal]?: {\n [key in keyof GlobalConfig['hooks']]?: true\n } | true\n }\n\n /**\n * Step task configurations.\n * These are the step types available for use in workflows.\n */\n steps: TaskConfig<string>[]\n\n /**\n * Seed workflows to create on plugin initialization.\n * These workflows are read-only and serve as templates.\n */\n seedWorkflows?: SeedWorkflow[]\n\n /**\n * Custom trigger configurations.\n */\n triggers?: TriggerConfig[]\n\n /**\n * Logging configuration.\n * Set to true to enable debug logging.\n */\n debug?: boolean\n}"],"names":[],"mappings":"AAmCA;;CAEC,GACD,WAqDC"}
1
+ {"version":3,"sources":["../../src/plugin/config-types.ts"],"sourcesContent":["import type {CollectionConfig, GlobalConfig, TaskConfig} from \"payload\"\n\n/**\n * Trigger definition for custom trigger configurations.\n */\nexport interface Trigger {\n slug: string\n label?: string\n parameters?: Array<{\n name: string\n type: string\n required?: boolean\n }>\n}\n\nexport type TriggerConfig = (config: WorkflowsPluginConfig) => Trigger\n\nexport type SeedWorkflow = {\n slug: string\n name: string\n description?: string\n triggers: Array<{\n type: string\n parameters?: Record<string, any>\n condition?: string\n }>\n steps: Array<{\n name: string\n slug?: string // Optional: auto-generated from name if not provided\n type: string\n input?: Record<string, any>\n dependencies?: string[] // Array of step slugs\n condition?: string\n }>\n}\n\n/**\n * Plugin configuration for the workflows automation plugin.\n */\nexport type WorkflowsPluginConfig<\n TCollection extends string = string,\n TGlobal extends string = string\n> = {\n /**\n * Whether the plugin is enabled. Defaults to true.\n */\n enabled?: boolean\n\n /**\n * Collection triggers configuration.\n * Keys are collection slugs, values configure which hooks to listen to.\n * Set to `true` to enable all default hooks (afterChange, afterDelete, afterRead).\n */\n collectionTriggers?: {\n [key in TCollection]?: {\n [key in keyof CollectionConfig['hooks']]?: true\n } | true\n }\n\n /**\n * Global triggers configuration.\n * Keys are global slugs, values configure which hooks to listen to.\n * Set to `true` to enable all default hooks (afterChange, afterRead).\n */\n globalTriggers?: {\n [key in TGlobal]?: {\n [key in keyof GlobalConfig['hooks']]?: true\n } | true\n }\n\n /**\n * Step task configurations.\n * These are the step types available for use in workflows.\n */\n steps: TaskConfig<string>[]\n\n /**\n * Seed workflows to create on plugin initialization.\n * These workflows are read-only and serve as templates.\n */\n seedWorkflows?: SeedWorkflow[]\n\n /**\n * Custom trigger configurations.\n */\n triggers?: TriggerConfig[]\n\n /**\n * Logging configuration.\n * Set to true to enable debug logging.\n */\n debug?: boolean\n}"],"names":[],"mappings":"AAoCA;;CAEC,GACD,WAqDC"}
@@ -243,10 +243,13 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
243
243
  triggerIds.push(trigger.id);
244
244
  logger.debug(`Created trigger: ${triggerName}`);
245
245
  }
246
+ // Helper to generate slug from name
247
+ const slugify = (str)=>str.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
246
248
  // Create steps in automation-steps collection and build workflow steps array
247
249
  const workflowSteps = [];
248
250
  for (const stepDef of seedWorkflow.steps){
249
251
  const stepName = `${seedWorkflow.name} - ${stepDef.name}`;
252
+ const stepSlug = stepDef.slug || slugify(stepDef.name);
250
253
  // Create step in automation-steps collection
251
254
  const step = await payload.create({
252
255
  collection: 'automation-steps',
@@ -260,11 +263,12 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
260
263
  // Add to workflow steps with relationship ID
261
264
  workflowSteps.push({
262
265
  step: step.id,
266
+ slug: stepSlug,
263
267
  stepName: stepDef.name,
264
268
  inputOverrides: stepDef.input || {},
265
269
  condition: stepDef.condition,
266
270
  dependencies: stepDef.dependencies?.map((dep)=>({
267
- stepName: dep
271
+ slug: dep
268
272
  }))
269
273
  });
270
274
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugin/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload'\n\nimport type { WorkflowsPluginConfig } from './config-types.js'\n\nimport { createTriggersCollection } from '../collections/Triggers.js'\nimport { createStepsCollection } from '../collections/Steps.js'\nimport { createWorkflowCollection } from '../collections/Workflow.js'\nimport { WorkflowRunsCollection } from '../collections/WorkflowRuns.js'\nimport { getConfigLogger, initializeLogger } from './logger.js'\nimport { createCollectionTriggerHook, createGlobalTriggerHook } from './trigger-hook.js'\n\nexport { getLogger } from './logger.js'\n\nconst applyCollectionsConfig = <T extends string>(\n pluginOptions: WorkflowsPluginConfig<T>,\n config: Config\n) => {\n if (!config.collections) {\n config.collections = []\n }\n\n // Add all automation collections\n config.collections.push(\n createTriggersCollection(pluginOptions),\n createStepsCollection(pluginOptions.steps),\n createWorkflowCollection(),\n WorkflowRunsCollection\n )\n}\n\ntype AnyHook =\n CollectionConfig['hooks'] extends infer H\n ? H extends Record<string, unknown>\n ? NonNullable<H[keyof H]> extends (infer U)[]\n ? U\n : never\n : never\n : never\n\nexport const workflowsPlugin =\n <TSlug extends string>(pluginOptions: WorkflowsPluginConfig<TSlug>) =>\n (config: Config): Config => {\n // If the plugin is disabled, return config unchanged\n if (pluginOptions.enabled === false) {\n return config\n }\n\n applyCollectionsConfig<TSlug>(pluginOptions, config)\n\n const logger = getConfigLogger()\n\n // Register collection hooks\n if (config.collections && pluginOptions.collectionTriggers) {\n for (const [collectionSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n const collectionIndex = config.collections.findIndex(c => c.slug === collectionSlug)\n if (collectionIndex === -1) {\n logger.warn(`Collection '${collectionSlug}' not found in config.collections`)\n continue\n }\n\n const collection = config.collections[collectionIndex]\n\n if (!collection.hooks) {\n collection.hooks = {}\n }\n\n const hooksToRegister = triggerConfig === true\n ? { afterChange: true, afterDelete: true, afterRead: true }\n : triggerConfig\n\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof collection.hooks\n\n if (!collection.hooks![hookKey]) {\n collection.hooks![hookKey] = []\n }\n\n const automationHook = createCollectionTriggerHook(collectionSlug, hookKey)\n\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n ;(collection.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for collection '${collectionSlug}'`)\n })\n }\n }\n\n // Register global hooks\n if (config.globals && pluginOptions.globalTriggers) {\n for (const [globalSlug, triggerConfig] of Object.entries(pluginOptions.globalTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n const globalIndex = config.globals.findIndex(g => g.slug === globalSlug)\n if (globalIndex === -1) {\n logger.warn(`Global '${globalSlug}' not found in config.globals`)\n continue\n }\n\n const global = config.globals[globalIndex]\n\n if (!global.hooks) {\n global.hooks = {}\n }\n\n const hooksToRegister = triggerConfig === true\n ? { afterChange: true, afterRead: true }\n : triggerConfig\n\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof global.hooks\n\n if (!global.hooks![hookKey]) {\n global.hooks![hookKey] = []\n }\n\n const automationHook = createGlobalTriggerHook(globalSlug, hookKey)\n\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n ;(global.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for global '${globalSlug}'`)\n })\n }\n }\n\n // Register step tasks\n if (!config.jobs) {\n config.jobs = { tasks: [] }\n }\n\n for (const step of pluginOptions.steps) {\n if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) {\n config.jobs?.tasks?.push(step)\n }\n }\n\n // Extend payload-jobs collection with automation context fields\n const existingJobsOverrides = config.jobs.jobsCollectionOverrides\n config.jobs.jobsCollectionOverrides = ({ defaultJobsCollection }) => {\n // Apply any existing overrides first\n const collection = existingJobsOverrides\n ? existingJobsOverrides({ defaultJobsCollection })\n : defaultJobsCollection\n\n return {\n ...collection,\n fields: [\n ...collection.fields,\n // Structured automation context fields for admin UI integration\n {\n name: 'automationWorkflow',\n type: 'relationship',\n relationTo: 'workflows',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Workflow that created this job',\n },\n },\n {\n name: 'automationWorkflowRun',\n type: 'relationship',\n relationTo: 'workflow-runs',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Workflow run that created this job',\n },\n },\n {\n name: 'automationTrigger',\n type: 'relationship',\n relationTo: 'automation-triggers',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Trigger that initiated the workflow',\n },\n },\n {\n name: 'automationStepName',\n type: 'text',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Name of the workflow step that created this job',\n },\n },\n ],\n admin: {\n ...collection.admin,\n listSearchableFields: [\n ...(collection.admin?.listSearchableFields || []),\n ],\n defaultColumns: [\n ...(collection.admin?.defaultColumns || ['taskSlug', 'queue', 'processing', 'completedAt']),\n ],\n },\n }\n }\n\n // Set up onInit\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n const logger = initializeLogger(payload)\n logger.info('Automation plugin initialized')\n\n const collectionCount = Object.keys(pluginOptions.collectionTriggers || {}).length\n const globalCount = Object.keys(pluginOptions.globalTriggers || {}).length\n const stepCount = pluginOptions.steps?.length || 0\n\n // Seed workflows if configured\n if (pluginOptions.seedWorkflows && pluginOptions.seedWorkflows.length > 0) {\n logger.info(`Seeding ${pluginOptions.seedWorkflows.length} workflows...`)\n\n for (const seedWorkflow of pluginOptions.seedWorkflows) {\n try {\n // Check if workflow already exists by slug\n const existingWorkflow = await payload.find({\n collection: 'workflows',\n where: {\n slug: {\n equals: seedWorkflow.slug,\n },\n },\n limit: 1,\n })\n\n if (existingWorkflow.docs.length > 0) {\n logger.debug(`Workflow '${seedWorkflow.slug}' already exists, skipping seed`)\n continue\n }\n\n // Create triggers in automation-triggers collection\n const triggerIds: (string | number)[] = []\n for (let i = 0; i < seedWorkflow.triggers.length; i++) {\n const triggerDef = seedWorkflow.triggers[i]\n const triggerName = `${seedWorkflow.name} - Trigger ${i + 1}`\n\n // Build trigger data based on type\n const triggerData: Record<string, unknown> = {\n name: triggerName,\n type: triggerDef.type,\n condition: triggerDef.condition,\n }\n\n // Map parameters to trigger fields based on type\n if (triggerDef.parameters) {\n if (triggerDef.type === 'collection-hook') {\n triggerData.collectionSlug = triggerDef.parameters.collectionSlug\n triggerData.hook = triggerDef.parameters.hook\n } else if (triggerDef.type === 'global-hook') {\n triggerData.globalSlug = triggerDef.parameters.globalSlug\n triggerData.hook = triggerDef.parameters.hook\n } else if (triggerDef.type === 'scheduled') {\n triggerData.schedule = triggerDef.parameters.schedule\n } else if (triggerDef.type === 'webhook') {\n triggerData.webhookPath = triggerDef.parameters.webhookPath\n }\n }\n\n const trigger = await payload.create({\n collection: 'automation-triggers',\n data: triggerData,\n })\n triggerIds.push(trigger.id)\n logger.debug(`Created trigger: ${triggerName}`)\n }\n\n // Create steps in automation-steps collection and build workflow steps array\n const workflowSteps: Array<{\n step: string | number\n stepName: string\n inputOverrides: Record<string, unknown>\n condition?: string\n dependencies?: Array<{ stepName: string }>\n }> = []\n\n for (const stepDef of seedWorkflow.steps) {\n const stepName = `${seedWorkflow.name} - ${stepDef.name}`\n\n // Create step in automation-steps collection\n const step = await payload.create({\n collection: 'automation-steps',\n data: {\n name: stepName,\n type: stepDef.type,\n config: stepDef.input || {},\n },\n })\n logger.debug(`Created step: ${stepName}`)\n\n // Add to workflow steps with relationship ID\n workflowSteps.push({\n step: step.id,\n stepName: stepDef.name,\n inputOverrides: stepDef.input || {},\n condition: stepDef.condition,\n dependencies: stepDef.dependencies?.map(dep => ({ stepName: dep })),\n })\n }\n\n // Create the workflow with relationship IDs\n await payload.create({\n collection: 'workflows',\n data: {\n slug: seedWorkflow.slug,\n name: seedWorkflow.name,\n description: seedWorkflow.description,\n triggers: triggerIds,\n steps: workflowSteps,\n readOnly: true,\n },\n })\n\n logger.info(`Seeded workflow: ${seedWorkflow.name}`)\n } catch (error) {\n logger.error(`Failed to seed workflow '${seedWorkflow.name}':`, error)\n }\n }\n }\n\n logger.info(`Plugin configuration: ${collectionCount} collection triggers, ${globalCount} global triggers, ${stepCount} steps`\n )\n }\n\n if (!config.custom) {\n config.custom = {}\n }\n if (!config.custom.pluginConfigs) {\n config.custom.pluginConfigs = {}\n }\n config.custom.pluginConfigs['@xtr-dev/payload-automation'] = pluginOptions\n\n return config\n }\n"],"names":["createTriggersCollection","createStepsCollection","createWorkflowCollection","WorkflowRunsCollection","getConfigLogger","initializeLogger","createCollectionTriggerHook","createGlobalTriggerHook","getLogger","applyCollectionsConfig","pluginOptions","config","collections","push","steps","workflowsPlugin","enabled","logger","collectionTriggers","collectionSlug","triggerConfig","Object","entries","collectionIndex","findIndex","c","slug","warn","collection","hooks","hooksToRegister","afterChange","afterDelete","afterRead","forEach","hookName","hookKey","automationHook","defineProperty","value","enumerable","debug","globals","globalTriggers","globalSlug","globalIndex","g","global","jobs","tasks","step","find","task","existingJobsOverrides","jobsCollectionOverrides","defaultJobsCollection","fields","name","type","relationTo","admin","position","readOnly","description","listSearchableFields","defaultColumns","incomingOnInit","onInit","payload","info","collectionCount","keys","length","globalCount","stepCount","seedWorkflows","seedWorkflow","existingWorkflow","where","equals","limit","docs","triggerIds","i","triggers","triggerDef","triggerName","triggerData","condition","parameters","hook","schedule","webhookPath","trigger","create","data","id","workflowSteps","stepDef","stepName","input","inputOverrides","dependencies","map","dep","error","custom","pluginConfigs"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/plugin/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload'\n\nimport type { WorkflowsPluginConfig } from './config-types.js'\n\nimport { createTriggersCollection } from '../collections/Triggers.js'\nimport { createStepsCollection } from '../collections/Steps.js'\nimport { createWorkflowCollection } from '../collections/Workflow.js'\nimport { WorkflowRunsCollection } from '../collections/WorkflowRuns.js'\nimport { getConfigLogger, initializeLogger } from './logger.js'\nimport { createCollectionTriggerHook, createGlobalTriggerHook } from './trigger-hook.js'\n\nexport { getLogger } from './logger.js'\n\nconst applyCollectionsConfig = <T extends string>(\n pluginOptions: WorkflowsPluginConfig<T>,\n config: Config\n) => {\n if (!config.collections) {\n config.collections = []\n }\n\n // Add all automation collections\n config.collections.push(\n createTriggersCollection(pluginOptions),\n createStepsCollection(pluginOptions.steps),\n createWorkflowCollection(),\n WorkflowRunsCollection\n )\n}\n\ntype AnyHook =\n CollectionConfig['hooks'] extends infer H\n ? H extends Record<string, unknown>\n ? NonNullable<H[keyof H]> extends (infer U)[]\n ? U\n : never\n : never\n : never\n\nexport const workflowsPlugin =\n <TSlug extends string>(pluginOptions: WorkflowsPluginConfig<TSlug>) =>\n (config: Config): Config => {\n // If the plugin is disabled, return config unchanged\n if (pluginOptions.enabled === false) {\n return config\n }\n\n applyCollectionsConfig<TSlug>(pluginOptions, config)\n\n const logger = getConfigLogger()\n\n // Register collection hooks\n if (config.collections && pluginOptions.collectionTriggers) {\n for (const [collectionSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n const collectionIndex = config.collections.findIndex(c => c.slug === collectionSlug)\n if (collectionIndex === -1) {\n logger.warn(`Collection '${collectionSlug}' not found in config.collections`)\n continue\n }\n\n const collection = config.collections[collectionIndex]\n\n if (!collection.hooks) {\n collection.hooks = {}\n }\n\n const hooksToRegister = triggerConfig === true\n ? { afterChange: true, afterDelete: true, afterRead: true }\n : triggerConfig\n\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof collection.hooks\n\n if (!collection.hooks![hookKey]) {\n collection.hooks![hookKey] = []\n }\n\n const automationHook = createCollectionTriggerHook(collectionSlug, hookKey)\n\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n ;(collection.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for collection '${collectionSlug}'`)\n })\n }\n }\n\n // Register global hooks\n if (config.globals && pluginOptions.globalTriggers) {\n for (const [globalSlug, triggerConfig] of Object.entries(pluginOptions.globalTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n const globalIndex = config.globals.findIndex(g => g.slug === globalSlug)\n if (globalIndex === -1) {\n logger.warn(`Global '${globalSlug}' not found in config.globals`)\n continue\n }\n\n const global = config.globals[globalIndex]\n\n if (!global.hooks) {\n global.hooks = {}\n }\n\n const hooksToRegister = triggerConfig === true\n ? { afterChange: true, afterRead: true }\n : triggerConfig\n\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof global.hooks\n\n if (!global.hooks![hookKey]) {\n global.hooks![hookKey] = []\n }\n\n const automationHook = createGlobalTriggerHook(globalSlug, hookKey)\n\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n ;(global.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for global '${globalSlug}'`)\n })\n }\n }\n\n // Register step tasks\n if (!config.jobs) {\n config.jobs = { tasks: [] }\n }\n\n for (const step of pluginOptions.steps) {\n if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) {\n config.jobs?.tasks?.push(step)\n }\n }\n\n // Extend payload-jobs collection with automation context fields\n const existingJobsOverrides = config.jobs.jobsCollectionOverrides\n config.jobs.jobsCollectionOverrides = ({ defaultJobsCollection }) => {\n // Apply any existing overrides first\n const collection = existingJobsOverrides\n ? existingJobsOverrides({ defaultJobsCollection })\n : defaultJobsCollection\n\n return {\n ...collection,\n fields: [\n ...collection.fields,\n // Structured automation context fields for admin UI integration\n {\n name: 'automationWorkflow',\n type: 'relationship',\n relationTo: 'workflows',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Workflow that created this job',\n },\n },\n {\n name: 'automationWorkflowRun',\n type: 'relationship',\n relationTo: 'workflow-runs',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Workflow run that created this job',\n },\n },\n {\n name: 'automationTrigger',\n type: 'relationship',\n relationTo: 'automation-triggers',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Trigger that initiated the workflow',\n },\n },\n {\n name: 'automationStepName',\n type: 'text',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Name of the workflow step that created this job',\n },\n },\n ],\n admin: {\n ...collection.admin,\n listSearchableFields: [\n ...(collection.admin?.listSearchableFields || []),\n ],\n defaultColumns: [\n ...(collection.admin?.defaultColumns || ['taskSlug', 'queue', 'processing', 'completedAt']),\n ],\n },\n }\n }\n\n // Set up onInit\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n const logger = initializeLogger(payload)\n logger.info('Automation plugin initialized')\n\n const collectionCount = Object.keys(pluginOptions.collectionTriggers || {}).length\n const globalCount = Object.keys(pluginOptions.globalTriggers || {}).length\n const stepCount = pluginOptions.steps?.length || 0\n\n // Seed workflows if configured\n if (pluginOptions.seedWorkflows && pluginOptions.seedWorkflows.length > 0) {\n logger.info(`Seeding ${pluginOptions.seedWorkflows.length} workflows...`)\n\n for (const seedWorkflow of pluginOptions.seedWorkflows) {\n try {\n // Check if workflow already exists by slug\n const existingWorkflow = await payload.find({\n collection: 'workflows',\n where: {\n slug: {\n equals: seedWorkflow.slug,\n },\n },\n limit: 1,\n })\n\n if (existingWorkflow.docs.length > 0) {\n logger.debug(`Workflow '${seedWorkflow.slug}' already exists, skipping seed`)\n continue\n }\n\n // Create triggers in automation-triggers collection\n const triggerIds: (string | number)[] = []\n for (let i = 0; i < seedWorkflow.triggers.length; i++) {\n const triggerDef = seedWorkflow.triggers[i]\n const triggerName = `${seedWorkflow.name} - Trigger ${i + 1}`\n\n // Build trigger data based on type\n const triggerData: Record<string, unknown> = {\n name: triggerName,\n type: triggerDef.type,\n condition: triggerDef.condition,\n }\n\n // Map parameters to trigger fields based on type\n if (triggerDef.parameters) {\n if (triggerDef.type === 'collection-hook') {\n triggerData.collectionSlug = triggerDef.parameters.collectionSlug\n triggerData.hook = triggerDef.parameters.hook\n } else if (triggerDef.type === 'global-hook') {\n triggerData.globalSlug = triggerDef.parameters.globalSlug\n triggerData.hook = triggerDef.parameters.hook\n } else if (triggerDef.type === 'scheduled') {\n triggerData.schedule = triggerDef.parameters.schedule\n } else if (triggerDef.type === 'webhook') {\n triggerData.webhookPath = triggerDef.parameters.webhookPath\n }\n }\n\n const trigger = await payload.create({\n collection: 'automation-triggers',\n data: triggerData,\n })\n triggerIds.push(trigger.id)\n logger.debug(`Created trigger: ${triggerName}`)\n }\n\n // Helper to generate slug from name\n const slugify = (str: string): string =>\n str.toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n\n // Create steps in automation-steps collection and build workflow steps array\n const workflowSteps: Array<{\n step: string | number\n slug: string\n stepName: string\n inputOverrides: Record<string, unknown>\n condition?: string\n dependencies?: Array<{ slug: string }>\n }> = []\n\n for (const stepDef of seedWorkflow.steps) {\n const stepName = `${seedWorkflow.name} - ${stepDef.name}`\n const stepSlug = stepDef.slug || slugify(stepDef.name)\n\n // Create step in automation-steps collection\n const step = await payload.create({\n collection: 'automation-steps',\n data: {\n name: stepName,\n type: stepDef.type,\n config: stepDef.input || {},\n },\n })\n logger.debug(`Created step: ${stepName}`)\n\n // Add to workflow steps with relationship ID\n workflowSteps.push({\n step: step.id,\n slug: stepSlug,\n stepName: stepDef.name,\n inputOverrides: stepDef.input || {},\n condition: stepDef.condition,\n dependencies: stepDef.dependencies?.map(dep => ({ slug: dep })),\n })\n }\n\n // Create the workflow with relationship IDs\n await payload.create({\n collection: 'workflows',\n data: {\n slug: seedWorkflow.slug,\n name: seedWorkflow.name,\n description: seedWorkflow.description,\n triggers: triggerIds,\n steps: workflowSteps,\n readOnly: true,\n },\n })\n\n logger.info(`Seeded workflow: ${seedWorkflow.name}`)\n } catch (error) {\n logger.error(`Failed to seed workflow '${seedWorkflow.name}':`, error)\n }\n }\n }\n\n logger.info(`Plugin configuration: ${collectionCount} collection triggers, ${globalCount} global triggers, ${stepCount} steps`\n )\n }\n\n if (!config.custom) {\n config.custom = {}\n }\n if (!config.custom.pluginConfigs) {\n config.custom.pluginConfigs = {}\n }\n config.custom.pluginConfigs['@xtr-dev/payload-automation'] = pluginOptions\n\n return config\n }\n"],"names":["createTriggersCollection","createStepsCollection","createWorkflowCollection","WorkflowRunsCollection","getConfigLogger","initializeLogger","createCollectionTriggerHook","createGlobalTriggerHook","getLogger","applyCollectionsConfig","pluginOptions","config","collections","push","steps","workflowsPlugin","enabled","logger","collectionTriggers","collectionSlug","triggerConfig","Object","entries","collectionIndex","findIndex","c","slug","warn","collection","hooks","hooksToRegister","afterChange","afterDelete","afterRead","forEach","hookName","hookKey","automationHook","defineProperty","value","enumerable","debug","globals","globalTriggers","globalSlug","globalIndex","g","global","jobs","tasks","step","find","task","existingJobsOverrides","jobsCollectionOverrides","defaultJobsCollection","fields","name","type","relationTo","admin","position","readOnly","description","listSearchableFields","defaultColumns","incomingOnInit","onInit","payload","info","collectionCount","keys","length","globalCount","stepCount","seedWorkflows","seedWorkflow","existingWorkflow","where","equals","limit","docs","triggerIds","i","triggers","triggerDef","triggerName","triggerData","condition","parameters","hook","schedule","webhookPath","trigger","create","data","id","slugify","str","toLowerCase","replace","workflowSteps","stepDef","stepName","stepSlug","input","inputOverrides","dependencies","map","dep","error","custom","pluginConfigs"],"mappings":"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"}
@@ -1,5 +1,3 @@
1
- export { createStep } from './create-step.js';
2
- export type { StepDefinition, StepTask } from './create-step.js';
3
1
  export { CreateDocumentStepTask } from './create-document.js';
4
2
  export { createDocumentHandler } from './create-document-handler.js';
5
3
  export { DeleteDocumentStepTask } from './delete-document.js';
@@ -1,5 +1,3 @@
1
- // Step factory for creating new steps
2
- export { createStep } from './create-step.js';
3
1
  // Built-in steps
4
2
  export { CreateDocumentStepTask } from './create-document.js';
5
3
  export { createDocumentHandler } from './create-document-handler.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/steps/index.ts"],"sourcesContent":["// Step factory for creating new steps\nexport { createStep } from './create-step.js'\nexport type { StepDefinition, StepTask } from './create-step.js'\n\n// Built-in steps\nexport { CreateDocumentStepTask } from './create-document.js'\nexport { createDocumentHandler } from './create-document-handler.js'\nexport { DeleteDocumentStepTask } from './delete-document.js'\nexport { deleteDocumentHandler } from './delete-document-handler.js'\nexport { HttpRequestStepTask } from './http-request.js'\nexport { httpStepHandler } from './http-request-handler.js'\n\nexport { ReadDocumentStepTask } from './read-document.js'\nexport { readDocumentHandler } from './read-document-handler.js'\nexport { SendEmailStepTask } from './send-email.js'\nexport { sendEmailHandler } from './send-email-handler.js'\nexport { UpdateDocumentStepTask } from './update-document.js'\nexport { updateDocumentHandler } from './update-document-handler.js'\n"],"names":["createStep","CreateDocumentStepTask","createDocumentHandler","DeleteDocumentStepTask","deleteDocumentHandler","HttpRequestStepTask","httpStepHandler","ReadDocumentStepTask","readDocumentHandler","SendEmailStepTask","sendEmailHandler","UpdateDocumentStepTask","updateDocumentHandler"],"mappings":"AAAA,sCAAsC;AACtC,SAASA,UAAU,QAAQ,mBAAkB;AAG7C,iBAAiB;AACjB,SAASC,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,qBAAqB,QAAQ,+BAA8B;AACpE,SAASC,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,qBAAqB,QAAQ,+BAA8B;AACpE,SAASC,mBAAmB,QAAQ,oBAAmB;AACvD,SAASC,eAAe,QAAQ,4BAA2B;AAE3D,SAASC,oBAAoB,QAAQ,qBAAoB;AACzD,SAASC,mBAAmB,QAAQ,6BAA4B;AAChE,SAASC,iBAAiB,QAAQ,kBAAiB;AACnD,SAASC,gBAAgB,QAAQ,0BAAyB;AAC1D,SAASC,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,qBAAqB,QAAQ,+BAA8B"}
1
+ {"version":3,"sources":["../../src/steps/index.ts"],"sourcesContent":["// Built-in steps\nexport { CreateDocumentStepTask } from './create-document.js'\nexport { createDocumentHandler } from './create-document-handler.js'\nexport { DeleteDocumentStepTask } from './delete-document.js'\nexport { deleteDocumentHandler } from './delete-document-handler.js'\nexport { HttpRequestStepTask } from './http-request.js'\nexport { httpStepHandler } from './http-request-handler.js'\n\nexport { ReadDocumentStepTask } from './read-document.js'\nexport { readDocumentHandler } from './read-document-handler.js'\nexport { SendEmailStepTask } from './send-email.js'\nexport { sendEmailHandler } from './send-email-handler.js'\nexport { UpdateDocumentStepTask } from './update-document.js'\nexport { updateDocumentHandler } from './update-document-handler.js'\n"],"names":["CreateDocumentStepTask","createDocumentHandler","DeleteDocumentStepTask","deleteDocumentHandler","HttpRequestStepTask","httpStepHandler","ReadDocumentStepTask","readDocumentHandler","SendEmailStepTask","sendEmailHandler","UpdateDocumentStepTask","updateDocumentHandler"],"mappings":"AAAA,iBAAiB;AACjB,SAASA,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,qBAAqB,QAAQ,+BAA8B;AACpE,SAASC,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,qBAAqB,QAAQ,+BAA8B;AACpE,SAASC,mBAAmB,QAAQ,oBAAmB;AACvD,SAASC,eAAe,QAAQ,4BAA2B;AAE3D,SAASC,oBAAoB,QAAQ,qBAAoB;AACzD,SAASC,mBAAmB,QAAQ,6BAA4B;AAChE,SAASC,iBAAiB,QAAQ,kBAAiB;AACnD,SAASC,gBAAgB,QAAQ,0BAAyB;AAC1D,SAASC,sBAAsB,QAAQ,uBAAsB;AAC7D,SAASC,qBAAqB,QAAQ,+BAA8B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtr-dev/payload-automation",
3
- "version": "0.0.52",
3
+ "version": "0.0.54",
4
4
  "description": "PayloadCMS Automation Plugin - Comprehensive workflow automation system with visual workflow building, execution tracking, and step types",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,66 +0,0 @@
1
- import type { Field, JsonObject, PayloadRequest, TaskConfig } from 'payload';
2
- /**
3
- * Configuration for creating a step with the factory.
4
- */
5
- export interface StepDefinition<TSlug extends string> {
6
- /** Unique identifier for the step */
7
- slug: TSlug;
8
- /** Human-readable label for the step (optional, defaults to slug) */
9
- label?: string;
10
- /** Input fields schema */
11
- inputSchema: Field[];
12
- /** Output fields schema */
13
- outputSchema: Field[];
14
- /**
15
- * Optional validation function. Throw an error if validation fails.
16
- * Runs before the execute function.
17
- */
18
- validate?: (input: JsonObject) => void;
19
- /**
20
- * The main execution function for the step.
21
- * Should return the output data on success, or throw an error on failure.
22
- */
23
- execute: (input: JsonObject, req: PayloadRequest) => Promise<JsonObject>;
24
- }
25
- /**
26
- * The result type returned by createStep.
27
- * Combines TaskConfig with the handler for convenience.
28
- */
29
- export type StepTask<TSlug extends string> = TaskConfig<TSlug>;
30
- /**
31
- * Creates a step definition that combines TaskConfig and handler in one place.
32
- *
33
- * This factory eliminates the need for separate `{step}.ts` and `{step}-handler.ts` files
34
- * by providing a single unified definition.
35
- *
36
- * @example
37
- * ```typescript
38
- * export const myStep = createStep({
39
- * slug: 'my-step',
40
- * inputSchema: [
41
- * { name: 'url', type: 'text', required: true }
42
- * ],
43
- * outputSchema: [
44
- * { name: 'result', type: 'json' }
45
- * ],
46
- * validate: (input) => {
47
- * if (!input.url) throw new Error('URL is required')
48
- * },
49
- * execute: async (input, req) => {
50
- * const response = await fetch(input.url)
51
- * return { result: await response.json() }
52
- * }
53
- * })
54
- * ```
55
- */
56
- export declare function createStep<TSlug extends string>(definition: StepDefinition<TSlug>): StepTask<TSlug>;
57
- /**
58
- * Helper type to extract input type from a step's inputSchema.
59
- * Note: This provides a basic type based on field names, not full type inference.
60
- */
61
- export type StepInput<T extends StepTask<string>> = T extends StepTask<infer _> ? Record<string, unknown> : never;
62
- /**
63
- * Helper type to extract output type from a step's outputSchema.
64
- * Note: This provides a basic type based on field names, not full type inference.
65
- */
66
- export type StepOutput<T extends StepTask<string>> = T extends StepTask<infer _> ? Record<string, unknown> : never;
@@ -1,59 +0,0 @@
1
- /**
2
- * Creates a step definition that combines TaskConfig and handler in one place.
3
- *
4
- * This factory eliminates the need for separate `{step}.ts` and `{step}-handler.ts` files
5
- * by providing a single unified definition.
6
- *
7
- * @example
8
- * ```typescript
9
- * export const myStep = createStep({
10
- * slug: 'my-step',
11
- * inputSchema: [
12
- * { name: 'url', type: 'text', required: true }
13
- * ],
14
- * outputSchema: [
15
- * { name: 'result', type: 'json' }
16
- * ],
17
- * validate: (input) => {
18
- * if (!input.url) throw new Error('URL is required')
19
- * },
20
- * execute: async (input, req) => {
21
- * const response = await fetch(input.url)
22
- * return { result: await response.json() }
23
- * }
24
- * })
25
- * ```
26
- */ export function createStep(definition) {
27
- const { slug, label, inputSchema, outputSchema, validate, execute } = definition;
28
- // Create the handler that wraps validation and execution
29
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
- const handler = async ({ input, req })=>{
31
- try {
32
- const jsonInput = input ?? {};
33
- // Run validation if provided
34
- if (validate) {
35
- validate(jsonInput);
36
- }
37
- // Execute the step
38
- const output = await execute(jsonInput, req);
39
- return {
40
- output,
41
- state: 'succeeded'
42
- };
43
- } catch (error) {
44
- return {
45
- errorMessage: error instanceof Error ? error.message : 'Unknown error',
46
- state: 'failed'
47
- };
48
- }
49
- };
50
- return {
51
- slug,
52
- label,
53
- handler,
54
- inputSchema,
55
- outputSchema
56
- };
57
- }
58
-
59
- //# sourceMappingURL=create-step.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/steps/create-step.ts"],"sourcesContent":["import type { Field, JsonObject, PayloadRequest, TaskConfig, TaskHandler } from 'payload'\n\n/**\n * Configuration for creating a step with the factory.\n */\nexport interface StepDefinition<TSlug extends string> {\n /** Unique identifier for the step */\n slug: TSlug\n /** Human-readable label for the step (optional, defaults to slug) */\n label?: string\n /** Input fields schema */\n inputSchema: Field[]\n /** Output fields schema */\n outputSchema: Field[]\n /**\n * Optional validation function. Throw an error if validation fails.\n * Runs before the execute function.\n */\n validate?: (input: JsonObject) => void\n /**\n * The main execution function for the step.\n * Should return the output data on success, or throw an error on failure.\n */\n execute: (input: JsonObject, req: PayloadRequest) => Promise<JsonObject>\n}\n\n/**\n * The result type returned by createStep.\n * Combines TaskConfig with the handler for convenience.\n */\nexport type StepTask<TSlug extends string> = TaskConfig<TSlug>\n\n/**\n * Creates a step definition that combines TaskConfig and handler in one place.\n *\n * This factory eliminates the need for separate `{step}.ts` and `{step}-handler.ts` files\n * by providing a single unified definition.\n *\n * @example\n * ```typescript\n * export const myStep = createStep({\n * slug: 'my-step',\n * inputSchema: [\n * { name: 'url', type: 'text', required: true }\n * ],\n * outputSchema: [\n * { name: 'result', type: 'json' }\n * ],\n * validate: (input) => {\n * if (!input.url) throw new Error('URL is required')\n * },\n * execute: async (input, req) => {\n * const response = await fetch(input.url)\n * return { result: await response.json() }\n * }\n * })\n * ```\n */\nexport function createStep<TSlug extends string>(\n definition: StepDefinition<TSlug>\n): StepTask<TSlug> {\n const { slug, label, inputSchema, outputSchema, validate, execute } = definition\n\n // Create the handler that wraps validation and execution\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handler = async ({ input, req }: any) => {\n try {\n const jsonInput = (input ?? {}) as JsonObject\n\n // Run validation if provided\n if (validate) {\n validate(jsonInput)\n }\n\n // Execute the step\n const output = await execute(jsonInput, req)\n return {\n output,\n state: 'succeeded'\n }\n } catch (error) {\n return {\n errorMessage: error instanceof Error ? error.message : 'Unknown error',\n state: 'failed'\n }\n }\n }\n\n return {\n slug,\n label,\n handler,\n inputSchema,\n outputSchema\n } as StepTask<TSlug>\n}\n\n/**\n * Helper type to extract input type from a step's inputSchema.\n * Note: This provides a basic type based on field names, not full type inference.\n */\nexport type StepInput<T extends StepTask<string>> = T extends StepTask<infer _>\n ? Record<string, unknown>\n : never\n\n/**\n * Helper type to extract output type from a step's outputSchema.\n * Note: This provides a basic type based on field names, not full type inference.\n */\nexport type StepOutput<T extends StepTask<string>> = T extends StepTask<infer _>\n ? Record<string, unknown>\n : never\n"],"names":["createStep","definition","slug","label","inputSchema","outputSchema","validate","execute","handler","input","req","jsonInput","output","state","error","errorMessage","Error","message"],"mappings":"AAgCA;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,OAAO,SAASA,WACdC,UAAiC;IAEjC,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAEC,WAAW,EAAEC,YAAY,EAAEC,QAAQ,EAAEC,OAAO,EAAE,GAAGN;IAEtE,yDAAyD;IACzD,8DAA8D;IAC9D,MAAMO,UAAU,OAAO,EAAEC,KAAK,EAAEC,GAAG,EAAO;QACxC,IAAI;YACF,MAAMC,YAAaF,SAAS,CAAC;YAE7B,6BAA6B;YAC7B,IAAIH,UAAU;gBACZA,SAASK;YACX;YAEA,mBAAmB;YACnB,MAAMC,SAAS,MAAML,QAAQI,WAAWD;YACxC,OAAO;gBACLE;gBACAC,OAAO;YACT;QACF,EAAE,OAAOC,OAAO;YACd,OAAO;gBACLC,cAAcD,iBAAiBE,QAAQF,MAAMG,OAAO,GAAG;gBACvDJ,OAAO;YACT;QACF;IACF;IAEA,OAAO;QACLX;QACAC;QACAK;QACAJ;QACAC;IACF;AACF"}