@xtr-dev/payload-automation 0.0.1

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.
Files changed (98) hide show
  1. package/README.md +73 -0
  2. package/dist/collections/Workflow.d.ts +3 -0
  3. package/dist/collections/Workflow.js +223 -0
  4. package/dist/collections/Workflow.js.map +1 -0
  5. package/dist/collections/WorkflowRuns.d.ts +2 -0
  6. package/dist/collections/WorkflowRuns.js +157 -0
  7. package/dist/collections/WorkflowRuns.js.map +1 -0
  8. package/dist/components/TriggerWorkflowButton.d.ts +7 -0
  9. package/dist/components/TriggerWorkflowButton.js +46 -0
  10. package/dist/components/TriggerWorkflowButton.js.map +1 -0
  11. package/dist/core/trigger-custom-workflow.d.ts +52 -0
  12. package/dist/core/trigger-custom-workflow.js +205 -0
  13. package/dist/core/trigger-custom-workflow.js.map +1 -0
  14. package/dist/core/workflow-executor.d.ts +86 -0
  15. package/dist/core/workflow-executor.js +456 -0
  16. package/dist/core/workflow-executor.js.map +1 -0
  17. package/dist/exports/client.d.ts +1 -0
  18. package/dist/exports/client.js +7 -0
  19. package/dist/exports/client.js.map +1 -0
  20. package/dist/exports/fields.d.ts +1 -0
  21. package/dist/exports/fields.js +6 -0
  22. package/dist/exports/fields.js.map +1 -0
  23. package/dist/exports/rsc.d.ts +1 -0
  24. package/dist/exports/rsc.js +3 -0
  25. package/dist/exports/rsc.js.map +1 -0
  26. package/dist/exports/views.d.ts +1 -0
  27. package/dist/exports/views.js +7 -0
  28. package/dist/exports/views.js.map +1 -0
  29. package/dist/index.d.ts +7 -0
  30. package/dist/index.js +8 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/plugin/config-types.d.ts +21 -0
  33. package/dist/plugin/config-types.js +3 -0
  34. package/dist/plugin/config-types.js.map +1 -0
  35. package/dist/plugin/cron-scheduler.d.ts +32 -0
  36. package/dist/plugin/cron-scheduler.js +537 -0
  37. package/dist/plugin/cron-scheduler.js.map +1 -0
  38. package/dist/plugin/index.d.ts +4 -0
  39. package/dist/plugin/index.js +66 -0
  40. package/dist/plugin/index.js.map +1 -0
  41. package/dist/plugin/init-collection-hooks.d.ts +4 -0
  42. package/dist/plugin/init-collection-hooks.js +63 -0
  43. package/dist/plugin/init-collection-hooks.js.map +1 -0
  44. package/dist/plugin/init-global-hooks.d.ts +3 -0
  45. package/dist/plugin/init-global-hooks.js +83 -0
  46. package/dist/plugin/init-global-hooks.js.map +1 -0
  47. package/dist/plugin/init-step-tasks.d.ts +3 -0
  48. package/dist/plugin/init-step-tasks.js +8 -0
  49. package/dist/plugin/init-step-tasks.js.map +1 -0
  50. package/dist/plugin/init-webhook.d.ts +2 -0
  51. package/dist/plugin/init-webhook.js +154 -0
  52. package/dist/plugin/init-webhook.js.map +1 -0
  53. package/dist/plugin/init-workflow-hooks.d.ts +6 -0
  54. package/dist/plugin/init-workflow-hooks.js +46 -0
  55. package/dist/plugin/init-workflow-hooks.js.map +1 -0
  56. package/dist/plugin/logger.d.ts +20 -0
  57. package/dist/plugin/logger.js +47 -0
  58. package/dist/plugin/logger.js.map +1 -0
  59. package/dist/steps/create-document-handler.d.ts +2 -0
  60. package/dist/steps/create-document-handler.js +36 -0
  61. package/dist/steps/create-document-handler.js.map +1 -0
  62. package/dist/steps/create-document.d.ts +46 -0
  63. package/dist/steps/create-document.js +55 -0
  64. package/dist/steps/create-document.js.map +1 -0
  65. package/dist/steps/delete-document-handler.d.ts +2 -0
  66. package/dist/steps/delete-document-handler.js +62 -0
  67. package/dist/steps/delete-document-handler.js.map +1 -0
  68. package/dist/steps/delete-document.d.ts +39 -0
  69. package/dist/steps/delete-document.js +47 -0
  70. package/dist/steps/delete-document.js.map +1 -0
  71. package/dist/steps/http-request-handler.d.ts +2 -0
  72. package/dist/steps/http-request-handler.js +14 -0
  73. package/dist/steps/http-request-handler.js.map +1 -0
  74. package/dist/steps/http-request.d.ts +12 -0
  75. package/dist/steps/http-request.js +19 -0
  76. package/dist/steps/http-request.js.map +1 -0
  77. package/dist/steps/index.d.ts +12 -0
  78. package/dist/steps/index.js +14 -0
  79. package/dist/steps/index.js.map +1 -0
  80. package/dist/steps/read-document-handler.d.ts +2 -0
  81. package/dist/steps/read-document-handler.js +53 -0
  82. package/dist/steps/read-document-handler.js.map +1 -0
  83. package/dist/steps/read-document.d.ts +46 -0
  84. package/dist/steps/read-document.js +75 -0
  85. package/dist/steps/read-document.js.map +1 -0
  86. package/dist/steps/send-email-handler.d.ts +2 -0
  87. package/dist/steps/send-email-handler.js +48 -0
  88. package/dist/steps/send-email-handler.js.map +1 -0
  89. package/dist/steps/send-email.d.ts +44 -0
  90. package/dist/steps/send-email.js +78 -0
  91. package/dist/steps/send-email.js.map +1 -0
  92. package/dist/steps/update-document-handler.d.ts +2 -0
  93. package/dist/steps/update-document-handler.js +40 -0
  94. package/dist/steps/update-document-handler.js.map +1 -0
  95. package/dist/steps/update-document.d.ts +46 -0
  96. package/dist/steps/update-document.js +63 -0
  97. package/dist/steps/update-document.js.map +1 -0
  98. package/package.json +133 -0
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @xtr-dev/payload-automation
2
+
3
+ A comprehensive workflow automation plugin for PayloadCMS 3.x that enables visual workflow building, execution tracking, and parallel processing.
4
+
5
+ ⚠️ **Pre-release Warning**: This package is currently in active development (v0.0.x). Breaking changes may occur before v1.0.0. Not recommended for production use.
6
+
7
+ ## Features
8
+
9
+ - 🔄 **Visual Workflow Builder** - Create complex workflows with drag-and-drop interface
10
+ - ⚡ **Parallel Execution** - Smart dependency resolution for optimal performance
11
+ - 🎯 **Multiple Triggers** - Collection hooks, webhooks, manual execution
12
+ - 📊 **Execution Tracking** - Complete history and monitoring of workflow runs
13
+ - 🔧 **Extensible Steps** - HTTP requests, document CRUD, email notifications
14
+ - 🔍 **JSONPath Integration** - Dynamic data interpolation and transformation
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @xtr-dev/payload-automation
20
+ # or
21
+ pnpm add @xtr-dev/payload-automation
22
+ # or
23
+ yarn add @xtr-dev/payload-automation
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```typescript
29
+ import { buildConfig } from 'payload'
30
+ import { payloadAutomation } from '@xtr-dev/payload-automation'
31
+
32
+ export default buildConfig({
33
+ // ... your config
34
+ plugins: [
35
+ payloadAutomation({
36
+ collections: ['posts', 'users'], // Collections to monitor
37
+ globals: ['settings'], // Globals to monitor
38
+ enabled: true,
39
+ }),
40
+ ],
41
+ })
42
+ ```
43
+
44
+ ## Step Types
45
+
46
+ - **HTTP Request** - Make external API calls
47
+ - **Create Document** - Create PayloadCMS documents
48
+ - **Read Document** - Query documents with filters
49
+ - **Update Document** - Modify existing documents
50
+ - **Delete Document** - Remove documents
51
+ - **Send Email** - Send notifications via PayloadCMS email
52
+
53
+ ## Data Resolution
54
+
55
+ Use JSONPath to access workflow data:
56
+
57
+ - `$.trigger.doc.id` - Access trigger document
58
+ - `$.steps.stepName.output` - Use previous step outputs
59
+ - `$.context` - Access workflow context
60
+
61
+ ## Requirements
62
+
63
+ - PayloadCMS ^3.45.0
64
+ - Node.js ^18.20.2 || >=20.9.0
65
+ - pnpm ^9 || ^10
66
+
67
+ ## Documentation
68
+
69
+ Full documentation coming soon. For now, explore the development environment in the repository for examples and patterns.
70
+
71
+ ## License
72
+
73
+ MIT
@@ -0,0 +1,3 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ import type { WorkflowsPluginConfig } from "../plugin/config-types.js";
3
+ export declare const createWorkflowCollection: <T extends string>(options: WorkflowsPluginConfig<T>) => CollectionConfig;
@@ -0,0 +1,223 @@
1
+ export const createWorkflowCollection = ({ collectionTriggers, steps, triggers })=>({
2
+ slug: 'workflows',
3
+ access: {
4
+ create: ()=>true,
5
+ delete: ()=>true,
6
+ read: ()=>true,
7
+ update: ()=>true
8
+ },
9
+ admin: {
10
+ defaultColumns: [
11
+ 'name',
12
+ 'updatedAt'
13
+ ],
14
+ description: 'Create and manage automated workflows.',
15
+ group: 'Automation',
16
+ useAsTitle: 'name'
17
+ },
18
+ fields: [
19
+ {
20
+ name: 'name',
21
+ type: 'text',
22
+ admin: {
23
+ description: 'Human-readable name for the workflow'
24
+ },
25
+ required: true
26
+ },
27
+ {
28
+ name: 'description',
29
+ type: 'textarea',
30
+ admin: {
31
+ description: 'Optional description of what this workflow does'
32
+ }
33
+ },
34
+ {
35
+ name: 'triggers',
36
+ type: 'array',
37
+ fields: [
38
+ {
39
+ name: 'type',
40
+ type: 'select',
41
+ options: [
42
+ 'collection-trigger',
43
+ 'webhook-trigger',
44
+ 'global-trigger',
45
+ 'cron-trigger',
46
+ ...(triggers || []).map((t)=>t.slug)
47
+ ]
48
+ },
49
+ {
50
+ name: 'collection',
51
+ type: 'select',
52
+ admin: {
53
+ condition: (_, siblingData)=>siblingData?.type === 'collection-trigger',
54
+ description: 'Collection that triggers the workflow'
55
+ },
56
+ options: Object.keys(collectionTriggers || {})
57
+ },
58
+ {
59
+ name: 'operation',
60
+ type: 'select',
61
+ admin: {
62
+ condition: (_, siblingData)=>siblingData?.type === 'collection-trigger',
63
+ description: 'Collection operation that triggers the workflow'
64
+ },
65
+ options: [
66
+ 'create',
67
+ 'delete',
68
+ 'read',
69
+ 'update'
70
+ ]
71
+ },
72
+ {
73
+ name: 'webhookPath',
74
+ type: 'text',
75
+ admin: {
76
+ condition: (_, siblingData)=>siblingData?.type === 'webhook-trigger',
77
+ description: 'URL path for the webhook (e.g., "my-webhook"). Full URL will be /api/workflows/webhook/my-webhook'
78
+ },
79
+ validate: (value, { siblingData })=>{
80
+ if (siblingData?.type === 'webhook-trigger' && !value) {
81
+ return 'Webhook path is required for webhook triggers';
82
+ }
83
+ return true;
84
+ }
85
+ },
86
+ {
87
+ name: 'global',
88
+ type: 'select',
89
+ admin: {
90
+ condition: (_, siblingData)=>siblingData?.type === 'global-trigger',
91
+ description: 'Global that triggers the workflow'
92
+ },
93
+ options: [] // Will be populated dynamically based on available globals
94
+ },
95
+ {
96
+ name: 'globalOperation',
97
+ type: 'select',
98
+ admin: {
99
+ condition: (_, siblingData)=>siblingData?.type === 'global-trigger',
100
+ description: 'Global operation that triggers the workflow'
101
+ },
102
+ options: [
103
+ 'update'
104
+ ]
105
+ },
106
+ {
107
+ name: 'cronExpression',
108
+ type: 'text',
109
+ admin: {
110
+ condition: (_, siblingData)=>siblingData?.type === 'cron-trigger',
111
+ description: 'Cron expression for scheduled execution (e.g., "0 0 * * *" for daily at midnight)',
112
+ placeholder: '0 0 * * *'
113
+ },
114
+ validate: (value, { siblingData })=>{
115
+ if (siblingData?.type === 'cron-trigger' && !value) {
116
+ return 'Cron expression is required for cron triggers';
117
+ }
118
+ // Validate cron expression format if provided
119
+ if (siblingData?.type === 'cron-trigger' && value) {
120
+ // Basic format validation - should be 5 parts separated by spaces
121
+ const cronParts = value.trim().split(/\s+/);
122
+ if (cronParts.length !== 5) {
123
+ return 'Invalid cron expression format. Expected 5 parts: "minute hour day month weekday" (e.g., "0 9 * * 1")';
124
+ }
125
+ // Additional validation could use node-cron but we avoid dynamic imports here
126
+ // The main validation happens at runtime in the cron scheduler
127
+ }
128
+ return true;
129
+ }
130
+ },
131
+ {
132
+ name: 'timezone',
133
+ type: 'text',
134
+ admin: {
135
+ condition: (_, siblingData)=>siblingData?.type === 'cron-trigger',
136
+ description: 'Timezone for cron execution (e.g., "America/New_York", "Europe/London"). Defaults to UTC.',
137
+ placeholder: 'UTC'
138
+ },
139
+ defaultValue: 'UTC',
140
+ validate: (value, { siblingData })=>{
141
+ if (siblingData?.type === 'cron-trigger' && value) {
142
+ try {
143
+ // Test if timezone is valid by trying to create a date with it
144
+ new Intl.DateTimeFormat('en', {
145
+ timeZone: value
146
+ });
147
+ return true;
148
+ } catch {
149
+ return `Invalid timezone: ${value}. Please use a valid IANA timezone identifier (e.g., "America/New_York", "Europe/London")`;
150
+ }
151
+ }
152
+ return true;
153
+ }
154
+ },
155
+ {
156
+ name: 'condition',
157
+ type: 'text',
158
+ admin: {
159
+ description: 'JSONPath expression that must evaluate to true for this trigger to execute the workflow (e.g., "$.doc.status == \'published\'")'
160
+ },
161
+ required: false
162
+ },
163
+ ...(triggers || []).flatMap((t)=>(t.inputs || []).map((f)=>({
164
+ ...f,
165
+ admin: {
166
+ ...f.admin || {},
167
+ condition: (...args)=>args[1]?.type === t.slug && (f.admin?.condition ? f.admin.condition.call(this, ...args) : true)
168
+ }
169
+ })))
170
+ ]
171
+ },
172
+ {
173
+ name: 'steps',
174
+ type: 'array',
175
+ fields: [
176
+ {
177
+ type: 'row',
178
+ fields: [
179
+ {
180
+ name: 'step',
181
+ type: 'select',
182
+ options: steps.map((t)=>t.slug)
183
+ },
184
+ {
185
+ name: 'name',
186
+ type: 'text'
187
+ }
188
+ ]
189
+ },
190
+ {
191
+ name: 'input',
192
+ type: 'json',
193
+ required: false
194
+ },
195
+ {
196
+ name: 'dependencies',
197
+ type: 'text',
198
+ admin: {
199
+ description: 'Step names that must complete before this step can run'
200
+ },
201
+ hasMany: true,
202
+ required: false
203
+ },
204
+ {
205
+ name: 'condition',
206
+ type: 'text',
207
+ admin: {
208
+ description: 'JSONPath expression that must evaluate to true for this step to execute (e.g., "$.trigger.doc.status == \'published\'")'
209
+ },
210
+ required: false
211
+ }
212
+ ]
213
+ }
214
+ ],
215
+ versions: {
216
+ drafts: {
217
+ autosave: false
218
+ },
219
+ maxPerDoc: 10
220
+ }
221
+ });
222
+
223
+ //# sourceMappingURL=Workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/collections/Workflow.ts"],"sourcesContent":["import type {CollectionConfig, Field} from 'payload'\n\nimport type {WorkflowsPluginConfig} from \"../plugin/config-types.js\"\n\nexport const createWorkflowCollection: <T extends string>(options: WorkflowsPluginConfig<T>) => CollectionConfig = ({\n collectionTriggers,\n steps,\n triggers\n }) => ({\n slug: 'workflows',\n access: {\n create: () => true,\n delete: () => true,\n read: () => true,\n update: () => true,\n },\n admin: {\n defaultColumns: ['name', '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: 'description',\n type: 'textarea',\n admin: {\n description: 'Optional description of what this workflow does',\n },\n },\n {\n name: 'triggers',\n type: 'array',\n fields: [\n {\n name: 'type',\n type: 'select',\n options: [\n 'collection-trigger',\n 'webhook-trigger',\n 'global-trigger',\n 'cron-trigger',\n ...(triggers || []).map(t => t.slug)\n ]\n },\n {\n name: 'collection',\n type: 'select',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'collection-trigger',\n description: 'Collection that triggers the workflow',\n },\n options: Object.keys(collectionTriggers || {})\n },\n {\n name: 'operation',\n type: 'select',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'collection-trigger',\n description: 'Collection operation that triggers the workflow',\n },\n options: [\n 'create',\n 'delete',\n 'read',\n 'update',\n ]\n },\n {\n name: 'webhookPath',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'webhook-trigger',\n description: 'URL path for the webhook (e.g., \"my-webhook\"). Full URL will be /api/workflows/webhook/my-webhook',\n },\n validate: (value: any, {siblingData}: any) => {\n if (siblingData?.type === 'webhook-trigger' && !value) {\n return 'Webhook path is required for webhook triggers'\n }\n return true\n }\n },\n {\n name: 'global',\n type: 'select',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'global-trigger',\n description: 'Global that triggers the workflow',\n },\n options: [] // Will be populated dynamically based on available globals\n },\n {\n name: 'globalOperation',\n type: 'select',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'global-trigger',\n description: 'Global operation that triggers the workflow',\n },\n options: [\n 'update'\n ]\n },\n {\n name: 'cronExpression',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'cron-trigger',\n description: 'Cron expression for scheduled execution (e.g., \"0 0 * * *\" for daily at midnight)',\n placeholder: '0 0 * * *'\n },\n validate: (value: any, {siblingData}: any) => {\n if (siblingData?.type === 'cron-trigger' && !value) {\n return 'Cron expression is required for cron triggers'\n }\n\n // Validate cron expression format if provided\n if (siblingData?.type === 'cron-trigger' && value) {\n // Basic format validation - should be 5 parts separated by spaces\n const cronParts = value.trim().split(/\\s+/)\n if (cronParts.length !== 5) {\n return 'Invalid cron expression format. Expected 5 parts: \"minute hour day month weekday\" (e.g., \"0 9 * * 1\")'\n }\n\n // Additional validation could use node-cron but we avoid dynamic imports here\n // The main validation happens at runtime in the cron scheduler\n }\n\n return true\n }\n },\n {\n name: 'timezone',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'cron-trigger',\n description: 'Timezone for cron execution (e.g., \"America/New_York\", \"Europe/London\"). Defaults to UTC.',\n placeholder: 'UTC'\n },\n defaultValue: 'UTC',\n validate: (value: any, {siblingData}: any) => {\n if (siblingData?.type === 'cron-trigger' && value) {\n try {\n // Test if timezone is valid by trying to create a date with it\n new Intl.DateTimeFormat('en', {timeZone: value})\n return true\n } catch {\n return `Invalid timezone: ${value}. Please use a valid IANA timezone identifier (e.g., \"America/New_York\", \"Europe/London\")`\n }\n }\n return true\n }\n },\n {\n name: 'condition',\n type: 'text',\n admin: {\n description: 'JSONPath expression that must evaluate to true for this trigger to execute the workflow (e.g., \"$.doc.status == \\'published\\'\")'\n },\n required: false\n },\n ...(triggers || []).flatMap(t => (t.inputs || []).map(f => ({\n ...f,\n admin: {\n ...(f.admin || {}),\n condition: (...args) => args[1]?.type === t.slug && (\n f.admin?.condition ?\n f.admin.condition.call(this, ...args) :\n true\n ),\n },\n } as Field)))\n ]\n },\n {\n name: 'steps',\n type: 'array',\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'step',\n type: 'select',\n options: steps.map(t => t.slug)\n },\n {\n name: 'name',\n type: 'text',\n }\n ]\n },\n {\n name: 'input',\n type: 'json',\n required: false\n },\n {\n name: 'dependencies',\n type: 'text',\n admin: {\n description: 'Step names that must complete before this step can run'\n },\n hasMany: true,\n required: false\n },\n {\n name: 'condition',\n type: 'text',\n admin: {\n description: 'JSONPath expression that must evaluate to true for this step to execute (e.g., \"$.trigger.doc.status == \\'published\\'\")'\n },\n required: false\n },\n ],\n }\n ],\n versions: {\n drafts: {\n autosave: false,\n },\n maxPerDoc: 10,\n },\n})\n"],"names":["createWorkflowCollection","collectionTriggers","steps","triggers","slug","access","create","delete","read","update","admin","defaultColumns","description","group","useAsTitle","fields","name","type","required","options","map","t","condition","_","siblingData","Object","keys","validate","value","placeholder","cronParts","trim","split","length","defaultValue","Intl","DateTimeFormat","timeZone","flatMap","inputs","f","args","call","hasMany","versions","drafts","autosave","maxPerDoc"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ export declare const WorkflowRunsCollection: CollectionConfig;
@@ -0,0 +1,157 @@
1
+ export const WorkflowRunsCollection = {
2
+ slug: 'workflow-runs',
3
+ access: {
4
+ create: ()=>true,
5
+ delete: ()=>true,
6
+ read: ()=>true,
7
+ update: ()=>true
8
+ },
9
+ admin: {
10
+ defaultColumns: [
11
+ 'workflow',
12
+ 'status',
13
+ 'triggeredBy',
14
+ 'startedAt',
15
+ 'duration'
16
+ ],
17
+ group: 'Automation',
18
+ pagination: {
19
+ defaultLimit: 50
20
+ },
21
+ useAsTitle: 'id'
22
+ },
23
+ fields: [
24
+ {
25
+ name: 'workflow',
26
+ type: 'relationship',
27
+ admin: {
28
+ description: 'Reference to the workflow that was executed'
29
+ },
30
+ relationTo: 'workflows',
31
+ required: true
32
+ },
33
+ {
34
+ name: 'workflowVersion',
35
+ type: 'number',
36
+ admin: {
37
+ description: 'Version of the workflow that was executed'
38
+ },
39
+ required: true
40
+ },
41
+ {
42
+ name: 'status',
43
+ type: 'select',
44
+ admin: {
45
+ description: 'Current execution status'
46
+ },
47
+ defaultValue: 'pending',
48
+ options: [
49
+ {
50
+ label: 'Pending',
51
+ value: 'pending'
52
+ },
53
+ {
54
+ label: 'Running',
55
+ value: 'running'
56
+ },
57
+ {
58
+ label: 'Completed',
59
+ value: 'completed'
60
+ },
61
+ {
62
+ label: 'Failed',
63
+ value: 'failed'
64
+ },
65
+ {
66
+ label: 'Cancelled',
67
+ value: 'cancelled'
68
+ }
69
+ ],
70
+ required: true
71
+ },
72
+ {
73
+ name: 'startedAt',
74
+ type: 'date',
75
+ admin: {
76
+ date: {
77
+ displayFormat: 'yyyy-MM-dd HH:mm:ss'
78
+ },
79
+ description: 'When execution began'
80
+ },
81
+ required: true
82
+ },
83
+ {
84
+ name: 'completedAt',
85
+ type: 'date',
86
+ admin: {
87
+ date: {
88
+ displayFormat: 'yyyy-MM-dd HH:mm:ss'
89
+ },
90
+ description: 'When execution finished'
91
+ }
92
+ },
93
+ {
94
+ name: 'duration',
95
+ type: 'number',
96
+ admin: {
97
+ description: 'Total execution time in milliseconds',
98
+ readOnly: true
99
+ }
100
+ },
101
+ {
102
+ name: 'context',
103
+ type: 'json'
104
+ },
105
+ {
106
+ name: 'inputs',
107
+ type: 'json',
108
+ admin: {
109
+ description: 'Input data provided when the workflow was triggered'
110
+ },
111
+ defaultValue: {},
112
+ required: true
113
+ },
114
+ {
115
+ name: 'outputs',
116
+ type: 'json',
117
+ admin: {
118
+ description: 'Final output data from completed steps'
119
+ }
120
+ },
121
+ {
122
+ name: 'triggeredBy',
123
+ type: 'text',
124
+ admin: {
125
+ description: 'User, system, or trigger type that initiated execution'
126
+ },
127
+ required: true
128
+ },
129
+ {
130
+ name: 'steps',
131
+ type: 'json',
132
+ admin: {
133
+ description: 'Array of step execution results'
134
+ },
135
+ defaultValue: [],
136
+ required: true
137
+ },
138
+ {
139
+ name: 'error',
140
+ type: 'textarea',
141
+ admin: {
142
+ description: 'Error message if workflow execution failed'
143
+ }
144
+ },
145
+ {
146
+ name: 'logs',
147
+ type: 'json',
148
+ admin: {
149
+ description: 'Detailed execution logs'
150
+ },
151
+ defaultValue: [],
152
+ required: true
153
+ }
154
+ ]
155
+ };
156
+
157
+ //# sourceMappingURL=WorkflowRuns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/collections/WorkflowRuns.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nexport const WorkflowRunsCollection: CollectionConfig = {\n slug: 'workflow-runs',\n access: {\n create: () => true,\n delete: () => true,\n read: () => true,\n update: () => true,\n },\n admin: {\n defaultColumns: ['workflow', 'status', 'triggeredBy', 'startedAt', 'duration'],\n group: 'Automation',\n pagination: {\n defaultLimit: 50,\n },\n useAsTitle: 'id',\n },\n fields: [\n {\n name: 'workflow',\n type: 'relationship',\n admin: {\n description: 'Reference to the workflow that was executed',\n },\n relationTo: 'workflows',\n required: true,\n },\n {\n name: 'workflowVersion',\n type: 'number',\n admin: {\n description: 'Version of the workflow that was executed',\n },\n required: true,\n },\n {\n name: 'status',\n type: 'select',\n admin: {\n description: 'Current execution status',\n },\n defaultValue: 'pending',\n options: [\n {\n label: 'Pending',\n value: 'pending',\n },\n {\n label: 'Running',\n value: 'running',\n },\n {\n label: 'Completed',\n value: 'completed',\n },\n {\n label: 'Failed',\n value: 'failed',\n },\n {\n label: 'Cancelled',\n value: 'cancelled',\n },\n ],\n required: true,\n },\n {\n name: 'startedAt',\n type: 'date',\n admin: {\n date: {\n displayFormat: 'yyyy-MM-dd HH:mm:ss',\n },\n description: 'When execution began',\n },\n required: true,\n },\n {\n name: 'completedAt',\n type: 'date',\n admin: {\n date: {\n displayFormat: 'yyyy-MM-dd HH:mm:ss',\n },\n description: 'When execution finished',\n },\n },\n {\n name: 'duration',\n type: 'number',\n admin: {\n description: 'Total execution time in milliseconds',\n readOnly: true,\n },\n },\n {\n name: 'context',\n type: 'json'\n },\n {\n name: 'inputs',\n type: 'json',\n admin: {\n description: 'Input data provided when the workflow was triggered',\n },\n defaultValue: {},\n required: true,\n },\n {\n name: 'outputs',\n type: 'json',\n admin: {\n description: 'Final output data from completed steps',\n },\n },\n {\n name: 'triggeredBy',\n type: 'text',\n admin: {\n description: 'User, system, or trigger type that initiated execution',\n },\n required: true,\n },\n {\n name: 'steps',\n type: 'json',\n admin: {\n description: 'Array of step execution results',\n },\n defaultValue: [],\n required: true,\n },\n {\n name: 'error',\n type: 'textarea',\n admin: {\n description: 'Error message if workflow execution failed',\n },\n },\n {\n name: 'logs',\n type: 'json',\n admin: {\n description: 'Detailed execution logs',\n },\n defaultValue: [],\n required: true,\n },\n ],\n}\n"],"names":["WorkflowRunsCollection","slug","access","create","delete","read","update","admin","defaultColumns","group","pagination","defaultLimit","useAsTitle","fields","name","type","description","relationTo","required","defaultValue","options","label","value","date","displayFormat","readOnly"],"mappings":"AAEA,OAAO,MAAMA,yBAA2C;IACtDC,MAAM;IACNC,QAAQ;QACNC,QAAQ,IAAM;QACdC,QAAQ,IAAM;QACdC,MAAM,IAAM;QACZC,QAAQ,IAAM;IAChB;IACAC,OAAO;QACLC,gBAAgB;YAAC;YAAY;YAAU;YAAe;YAAa;SAAW;QAC9EC,OAAO;QACPC,YAAY;YACVC,cAAc;QAChB;QACAC,YAAY;IACd;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;YACAC,YAAY;YACZC,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;YACAE,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;YACAG,cAAc;YACdC,SAAS;gBACP;oBACEC,OAAO;oBACPC,OAAO;gBACT;gBACA;oBACED,OAAO;oBACPC,OAAO;gBACT;gBACA;oBACED,OAAO;oBACPC,OAAO;gBACT;gBACA;oBACED,OAAO;oBACPC,OAAO;gBACT;gBACA;oBACED,OAAO;oBACPC,OAAO;gBACT;aACD;YACDJ,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLgB,MAAM;oBACJC,eAAe;gBACjB;gBACAR,aAAa;YACf;YACAE,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLgB,MAAM;oBACJC,eAAe;gBACjB;gBACAR,aAAa;YACf;QACF;QACA;YACEF,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;gBACbS,UAAU;YACZ;QACF;QACA;YACEX,MAAM;YACNC,MAAM;QACR;QACA;YACED,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;YACAG,cAAc,CAAC;YACfD,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;QACF;QACA;YACEF,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;YACAE,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;YACAG,cAAc,EAAE;YAChBD,UAAU;QACZ;QACA;YACEJ,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;QACF;QACA;YACEF,MAAM;YACNC,MAAM;YACNR,OAAO;gBACLS,aAAa;YACf;YACAG,cAAc,EAAE;YAChBD,UAAU;QACZ;KACD;AACH,EAAC"}
@@ -0,0 +1,7 @@
1
+ interface TriggerWorkflowButtonProps {
2
+ workflowId: string;
3
+ workflowName: string;
4
+ triggerSlug?: string;
5
+ }
6
+ export declare const TriggerWorkflowButton: React.FC<TriggerWorkflowButtonProps>;
7
+ export {};
@@ -0,0 +1,46 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Button, toast } from '@payloadcms/ui';
4
+ import { useState } from 'react';
5
+ export const TriggerWorkflowButton = ({ workflowId, workflowName, triggerSlug = 'manual-trigger' })=>{
6
+ const [loading, setLoading] = useState(false);
7
+ const handleTrigger = async ()=>{
8
+ setLoading(true);
9
+ try {
10
+ const response = await fetch('/api/workflows/trigger-custom', {
11
+ method: 'POST',
12
+ headers: {
13
+ 'Content-Type': 'application/json'
14
+ },
15
+ body: JSON.stringify({
16
+ workflowId,
17
+ triggerSlug,
18
+ data: {
19
+ triggeredAt: new Date().toISOString(),
20
+ source: 'admin-button'
21
+ }
22
+ })
23
+ });
24
+ if (!response.ok) {
25
+ const error = await response.json();
26
+ throw new Error(error.message || 'Failed to trigger workflow');
27
+ }
28
+ const result = await response.json();
29
+ toast.success(`Workflow "${workflowName}" triggered successfully! Run ID: ${result.runId}`);
30
+ } catch (error) {
31
+ console.error('Error triggering workflow:', error);
32
+ toast.error(`Failed to trigger workflow: ${error instanceof Error ? error.message : 'Unknown error'}`);
33
+ } finally{
34
+ setLoading(false);
35
+ }
36
+ };
37
+ return /*#__PURE__*/ _jsx(Button, {
38
+ onClick: handleTrigger,
39
+ disabled: loading,
40
+ size: "small",
41
+ buttonStyle: "secondary",
42
+ children: loading ? 'Triggering...' : 'Trigger Workflow'
43
+ });
44
+ };
45
+
46
+ //# sourceMappingURL=TriggerWorkflowButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/TriggerWorkflowButton.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast } from '@payloadcms/ui'\nimport { useState } from 'react'\n\ninterface TriggerWorkflowButtonProps {\n workflowId: string\n workflowName: string\n triggerSlug?: string\n}\n\nexport const TriggerWorkflowButton: React.FC<TriggerWorkflowButtonProps> = ({\n workflowId,\n workflowName,\n triggerSlug = 'manual-trigger'\n}) => {\n const [loading, setLoading] = useState(false)\n\n const handleTrigger = async () => {\n setLoading(true)\n \n try {\n const response = await fetch('/api/workflows/trigger-custom', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n workflowId,\n triggerSlug,\n data: {\n triggeredAt: new Date().toISOString(),\n source: 'admin-button'\n }\n }),\n })\n\n if (!response.ok) {\n const error = await response.json()\n throw new Error(error.message || 'Failed to trigger workflow')\n }\n\n const result = await response.json()\n \n toast.success(`Workflow \"${workflowName}\" triggered successfully! Run ID: ${result.runId}`)\n } catch (error) {\n console.error('Error triggering workflow:', error)\n toast.error(`Failed to trigger workflow: ${error instanceof Error ? error.message : 'Unknown error'}`)\n } finally {\n setLoading(false)\n }\n }\n\n return (\n <Button\n onClick={handleTrigger}\n disabled={loading}\n size=\"small\"\n buttonStyle=\"secondary\"\n >\n {loading ? 'Triggering...' : 'Trigger Workflow'}\n </Button>\n )\n}"],"names":["Button","toast","useState","TriggerWorkflowButton","workflowId","workflowName","triggerSlug","loading","setLoading","handleTrigger","response","fetch","method","headers","body","JSON","stringify","data","triggeredAt","Date","toISOString","source","ok","error","json","Error","message","result","success","runId","console","onClick","disabled","size","buttonStyle"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,KAAK,QAAQ,iBAAgB;AAC9C,SAASC,QAAQ,QAAQ,QAAO;AAQhC,OAAO,MAAMC,wBAA8D,CAAC,EAC1EC,UAAU,EACVC,YAAY,EACZC,cAAc,gBAAgB,EAC/B;IACC,MAAM,CAACC,SAASC,WAAW,GAAGN,SAAS;IAEvC,MAAMO,gBAAgB;QACpBD,WAAW;QAEX,IAAI;YACF,MAAME,WAAW,MAAMC,MAAM,iCAAiC;gBAC5DC,QAAQ;gBACRC,SAAS;oBACP,gBAAgB;gBAClB;gBACAC,MAAMC,KAAKC,SAAS,CAAC;oBACnBZ;oBACAE;oBACAW,MAAM;wBACJC,aAAa,IAAIC,OAAOC,WAAW;wBACnCC,QAAQ;oBACV;gBACF;YACF;YAEA,IAAI,CAACX,SAASY,EAAE,EAAE;gBAChB,MAAMC,QAAQ,MAAMb,SAASc,IAAI;gBACjC,MAAM,IAAIC,MAAMF,MAAMG,OAAO,IAAI;YACnC;YAEA,MAAMC,SAAS,MAAMjB,SAASc,IAAI;YAElCvB,MAAM2B,OAAO,CAAC,CAAC,UAAU,EAAEvB,aAAa,kCAAkC,EAAEsB,OAAOE,KAAK,EAAE;QAC5F,EAAE,OAAON,OAAO;YACdO,QAAQP,KAAK,CAAC,8BAA8BA;YAC5CtB,MAAMsB,KAAK,CAAC,CAAC,4BAA4B,EAAEA,iBAAiBE,QAAQF,MAAMG,OAAO,GAAG,iBAAiB;QACvG,SAAU;YACRlB,WAAW;QACb;IACF;IAEA,qBACE,KAACR;QACC+B,SAAStB;QACTuB,UAAUzB;QACV0B,MAAK;QACLC,aAAY;kBAEX3B,UAAU,kBAAkB;;AAGnC,EAAC"}
@@ -0,0 +1,52 @@
1
+ import type { Payload, PayloadRequest } from 'payload';
2
+ export interface CustomTriggerOptions {
3
+ /**
4
+ * Data to pass to the workflow execution context
5
+ */
6
+ data?: Record<string, unknown>;
7
+ /**
8
+ * Optional PayloadRequest to use for the workflow execution
9
+ * If not provided, a minimal request will be created
10
+ */
11
+ req?: PayloadRequest;
12
+ /**
13
+ * The slug of the custom trigger to execute
14
+ */
15
+ slug: string;
16
+ /**
17
+ * Optional user information for tracking who triggered the workflow
18
+ */
19
+ user?: {
20
+ email?: string;
21
+ id?: string;
22
+ };
23
+ }
24
+ export interface TriggerResult {
25
+ error?: string;
26
+ runId: number | string;
27
+ status: 'failed' | 'triggered';
28
+ workflowId: string;
29
+ workflowName: string;
30
+ }
31
+ /**
32
+ * Programmatically trigger workflows that have a matching custom trigger
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // In your onInit or elsewhere in your code
37
+ * await triggerCustomWorkflow(payload, {
38
+ * slug: 'data-import',
39
+ * data: {
40
+ * source: 'external-api',
41
+ * recordCount: 100,
42
+ * importedAt: new Date().toISOString()
43
+ * }
44
+ * })
45
+ * ```
46
+ */
47
+ export declare function triggerCustomWorkflow(payload: Payload, options: CustomTriggerOptions): Promise<TriggerResult[]>;
48
+ /**
49
+ * Helper function to trigger a single workflow by ID with custom trigger data
50
+ * This is useful when you know exactly which workflow you want to trigger
51
+ */
52
+ export declare function triggerWorkflowById(payload: Payload, workflowId: string, triggerSlug: string, data?: Record<string, unknown>, req?: PayloadRequest): Promise<TriggerResult>;