@xtr-dev/payload-automation 0.0.53 → 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
@@ -111,6 +111,7 @@ const exampleWorkflows: SeedWorkflow[] = [
111
111
  steps: [
112
112
  {
113
113
  name: 'Validate Order',
114
+ slug: 'validate-order', // Unique identifier for this step
114
115
  type: 'http-request-step',
115
116
  input: {
116
117
  url: 'https://api.example.com/validate',
@@ -123,6 +124,7 @@ const exampleWorkflows: SeedWorkflow[] = [
123
124
  },
124
125
  {
125
126
  name: 'Check Inventory',
127
+ slug: 'check-inventory',
126
128
  type: 'http-request-step',
127
129
  input: {
128
130
  url: 'https://api.example.com/inventory/check',
@@ -131,11 +133,12 @@ const exampleWorkflows: SeedWorkflow[] = [
131
133
  items: '{{trigger.doc.items}}',
132
134
  },
133
135
  },
134
- // This step runs only after Validate Order succeeds
135
- dependencies: ['Validate Order'],
136
+ // Dependencies reference other steps by slug
137
+ dependencies: ['validate-order'],
136
138
  },
137
139
  {
138
140
  name: 'Create Shipment',
141
+ slug: 'create-shipment',
139
142
  type: 'create-document',
140
143
  input: {
141
144
  collection: 'shipments',
@@ -146,18 +149,19 @@ const exampleWorkflows: SeedWorkflow[] = [
146
149
  },
147
150
  },
148
151
  // This step waits for both validation and inventory check
149
- dependencies: ['Validate Order', 'Check Inventory'],
152
+ dependencies: ['validate-order', 'check-inventory'],
150
153
  },
151
154
  {
152
155
  name: 'Send Confirmation Email',
156
+ slug: 'send-email',
153
157
  type: 'send-email',
154
158
  input: {
155
159
  to: '{{trigger.doc.customer.email}}',
156
160
  subject: 'Order Confirmed',
157
161
  text: 'Your order {{trigger.doc.id}} has been confirmed!',
158
162
  },
159
- // Only send email after shipment is created
160
- dependencies: ['Create Shipment'],
163
+ // Dependencies reference step slugs
164
+ dependencies: ['create-shipment'],
161
165
  },
162
166
  ],
163
167
  },
@@ -181,7 +185,7 @@ See [docs/SEEDING_WORKFLOWS.md](./docs/SEEDING_WORKFLOWS.md) for detailed docume
181
185
 
182
186
  ## Step Dependencies
183
187
 
184
- Steps can declare dependencies on other steps to control execution order. The workflow executor uses topological sorting to determine the optimal execution order.
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.
185
189
 
186
190
  ### How Dependencies Work
187
191
 
@@ -189,6 +193,7 @@ Steps can declare dependencies on other steps to control execution order. The wo
189
193
  - **Sequential Execution**: Steps with dependencies wait for their dependencies to complete successfully
190
194
  - **Multiple Dependencies**: A step can depend on multiple other steps (all must succeed)
191
195
  - **Failure Handling**: If a dependency fails, the dependent step is skipped
196
+ - **Slug-based**: Dependencies reference step `slug` fields, not names or positions
192
197
 
193
198
  ### Example: Parallel and Sequential Steps
194
199
 
@@ -196,18 +201,21 @@ Steps can declare dependencies on other steps to control execution order. The wo
196
201
  steps: [
197
202
  {
198
203
  name: 'Fetch User Data',
204
+ slug: 'fetch-user',
199
205
  type: 'http-request-step',
200
206
  // No dependencies - runs immediately
201
207
  },
202
208
  {
203
209
  name: 'Fetch Order Data',
210
+ slug: 'fetch-orders',
204
211
  type: 'http-request-step',
205
- // No dependencies - runs in parallel with Fetch User Data
212
+ // No dependencies - runs in parallel with fetch-user
206
213
  },
207
214
  {
208
215
  name: 'Generate Report',
216
+ slug: 'generate-report',
209
217
  type: 'http-request-step',
210
- dependencies: ['Fetch User Data', 'Fetch Order Data'],
218
+ dependencies: ['fetch-user', 'fetch-orders'], // Reference by slug
211
219
  // Waits for both API calls to complete
212
220
  input: {
213
221
  url: 'https://api.example.com/reports',
@@ -227,8 +235,9 @@ Use `{{steps.<stepName>.output.<field>}}` to reference data from completed steps
227
235
  ```typescript
228
236
  {
229
237
  name: 'Process Result',
238
+ slug: 'process-result',
230
239
  type: 'create-document',
231
- dependencies: ['API Call'],
240
+ dependencies: ['api-call'], // Reference by slug
232
241
  input: {
233
242
  collection: 'results',
234
243
  data: {
@@ -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":"AAEA;;;CAGC,GACD,OAAO,MAAMA,2BAA2B;IACtC,OAAO;QACLC,MAAM;QACNC,QAAQ;YACNC,QAAQ,IAAM;YACdC,QAAQ,CAAC,EAAEC,GAAG,EAAEC,IAAI,EAAE;gBACpB,0CAA0C;gBAC1C,IAAIA,MAAMC,aAAa,MAAM;oBAC3B,OAAO;gBACT;gBACA,OAAO;YACT;YACAC,MAAM,IAAM;YACZC,QAAQ,CAAC,EAAEJ,GAAG,EAAEC,IAAI,EAAE;gBACpB,yCAAyC;gBACzC,IAAIA,MAAMC,aAAa,MAAM;oBAC3B,OAAO;gBACT;gBACA,OAAO;YACT;QACF;QACAG,OAAO;YACLC,gBAAgB;gBAAC;gBAAQ;gBAAQ;gBAAY;gBAAW;aAAY;YACpEC,aAAa;YACbC,OAAO;YACPC,YAAY;QACd;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;gBACf;gBACAM,UAAU;YACZ;YACA;gBACEF,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;oBACbO,UAAU;gBACZ;gBACAC,OAAO;gBACPC,QAAQ;YACV;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;oBACbO,UAAU;oBACVZ,UAAU;gBACZ;gBACAe,cAAc;YAChB;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLa,YAAY;wBACVC,OAAO;oBACT;oBACAC,WAAW,CAACnB,OAASA,MAAMC,aAAa;gBAC1C;YACF;YACA;gBACES,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;gBACf;YACF;YACA;gBACEI,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;oBACbO,UAAU;gBACZ;gBACAG,cAAc;YAChB;YACA,4DAA4D;YAC5D;gBACEN,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;gBACf;gBACAc,SAAS;gBACTC,YAAY;YACd;YACA,6CAA6C;YAC7C;gBACEX,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;gBACf;gBACAG,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAe,YAAY;wBACZT,UAAU;oBACZ;oBACA;wBACEF,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;oBACF;oBACA;wBACEI,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAU,cAAc,CAAC;oBACjB;oBACA;wBACEN,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;4BACbgB,UAAU;wBACZ;oBACF;oBACA;wBACEZ,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAG,QAAQ;4BACN;gCACEC,MAAM;gCACNC,MAAM;gCACNP,OAAO;oCACLE,aAAa;gCACf;gCACAM,UAAU;4BACZ;yBACD;oBACH;oBACA,0BAA0B;oBAC1B;wBACEF,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;4BACbiB,QAAQ;wBACV;oBACF;iBACD;YACH;YACA,2BAA2B;YAC3B;gBACEZ,MAAM;gBACNa,OAAO;gBACPpB,OAAO;oBACLqB,eAAe;gBACjB;gBACAhB,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAU,cAAc;wBACdU,SAAS;4BACP;gCAAEF,OAAO;gCAAiBG,OAAO;4BAAO;4BACxC;gCAAEH,OAAO;gCAAyBG,OAAO;4BAAW;4BACpD;gCAAEH,OAAO;gCAAqBG,OAAO;4BAAQ;yBAC9C;oBACH;oBACA;wBACEjB,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLe,WAAW,CAACS,GAAGC,cAAgBA,aAAaC,kBAAkB;4BAC9DxB,aAAa;wBACf;wBACAU,cAAc;oBAChB;oBACA;wBACEN,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLe,WAAW,CAACS,GAAGC,cAAgBA,aAAaC,kBAAkB;4BAC9DxB,aAAa;wBACf;wBACAU,cAAc;oBAChB;oBACA;wBACEN,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAU,cAAc;oBAChB;iBACD;YACH;SACD;QACDe,OAAO;YACLC,aAAa;gBACX,6CAA6C;gBAC7C,OAAO,EAAEC,GAAG,EAAElC,GAAG,EAAE;oBACjB,MAAMmC,UAAUnC,IAAImC,OAAO;oBAE3B,8BAA8B;oBAC9B,IAAID,IAAIE,QAAQ,IAAIC,MAAMC,OAAO,CAACJ,IAAIE,QAAQ,GAAG;wBAC/C,KAAK,MAAMG,aAAaL,IAAIE,QAAQ,CAAE;4BACpC,MAAMI,KAAK,OAAOD,cAAc,WAAWA,UAAUC,EAAE,GAAGD;4BAC1D,IAAIC,IAAI;gCACN,IAAI;oCACF,qCAAqC;oCACrC,MAAMC,QAAQ,MAAMN,QAAQM,KAAK,CAAC;wCAChCC,YAAY;wCACZC,OAAO;4CACLP,UAAU;gDAAEQ,UAAUJ;4CAAG;wCAC3B;oCACF;oCACA,MAAML,QAAQ/B,MAAM,CAAC;wCACnBsC,YAAY;wCACZF;wCACAvC,MAAM;4CAAE4C,YAAYJ,MAAMK,SAAS;wCAAC;oCACtC;gCACF,EAAE,OAAM;gCACN,kDAAkD;gCACpD;4BACF;wBACF;oBACF;oBAEA,2BAA2B;oBAC3B,IAAIZ,IAAIa,KAAK,IAAIV,MAAMC,OAAO,CAACJ,IAAIa,KAAK,GAAG;wBACzC,MAAMC,UAAU,IAAIC;wBACpB,KAAK,MAAMC,gBAAgBhB,IAAIa,KAAK,CAAE;4BACpC,MAAMI,SAAS,OAAOD,aAAaE,IAAI,KAAK,WACxCF,aAAaE,IAAI,CAACZ,EAAE,GACpBU,aAAaE,IAAI;4BACrB,IAAID,QAAQH,QAAQK,GAAG,CAACF;wBAC1B;wBAEA,KAAK,MAAMA,UAAUH,QAAS;4BAC5B,IAAI;gCACF,kCAAkC;gCAClC,MAAMP,QAAQ,MAAMN,QAAQM,KAAK,CAAC;oCAChCC,YAAY;oCACZC,OAAO;wCACL,cAAc;4CAAEW,QAAQH;wCAAO;oCACjC;gCACF;gCACA,MAAMhB,QAAQ/B,MAAM,CAAC;oCACnBsC,YAAY;oCACZF,IAAIW;oCACJlD,MAAM;wCAAE4C,YAAYJ,MAAMK,SAAS;oCAAC;gCACtC;4BACF,EAAE,OAAM;4BACN,+CAA+C;4BACjD;wBACF;oBACF;oBAEA,OAAOZ;gBACT;aACD;QACH;QACAqB,UAAU;YACRC,QAAQ;gBACNC,UAAU;YACZ;YACAC,WAAW;QACb;IACF;AACF,EAAC"}
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtr-dev/payload-automation",
3
- "version": "0.0.53",
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",