@xtr-dev/payload-automation 0.0.42 → 0.0.45

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 (76) hide show
  1. package/README.md +221 -49
  2. package/dist/collections/Steps.d.ts +6 -0
  3. package/dist/collections/Steps.js +166 -0
  4. package/dist/collections/Steps.js.map +1 -0
  5. package/dist/collections/Triggers.d.ts +7 -0
  6. package/dist/collections/Triggers.js +224 -0
  7. package/dist/collections/Triggers.js.map +1 -0
  8. package/dist/collections/Workflow.d.ts +5 -2
  9. package/dist/collections/Workflow.js +179 -39
  10. package/dist/collections/Workflow.js.map +1 -1
  11. package/dist/collections/WorkflowRuns.d.ts +4 -0
  12. package/dist/collections/WorkflowRuns.js +219 -24
  13. package/dist/collections/WorkflowRuns.js.map +1 -1
  14. package/dist/components/WorkflowBuilder/WorkflowBuilder.js.map +1 -1
  15. package/dist/core/expression-engine.d.ts +58 -0
  16. package/dist/core/expression-engine.js +191 -0
  17. package/dist/core/expression-engine.js.map +1 -0
  18. package/dist/core/workflow-executor.d.ts +70 -56
  19. package/dist/core/workflow-executor.js +354 -677
  20. package/dist/core/workflow-executor.js.map +1 -1
  21. package/dist/exports/client.js +1 -3
  22. package/dist/exports/client.js.map +1 -1
  23. package/dist/exports/views.js +2 -4
  24. package/dist/exports/views.js.map +1 -1
  25. package/dist/fields/parameter.js +8 -3
  26. package/dist/fields/parameter.js.map +1 -1
  27. package/dist/index.d.ts +3 -2
  28. package/dist/index.js +1 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/plugin/config-types.d.ts +43 -5
  31. package/dist/plugin/config-types.js +3 -1
  32. package/dist/plugin/config-types.js.map +1 -1
  33. package/dist/plugin/index.d.ts +1 -1
  34. package/dist/plugin/index.js +82 -28
  35. package/dist/plugin/index.js.map +1 -1
  36. package/dist/plugin/trigger-hook.d.ts +13 -0
  37. package/dist/plugin/trigger-hook.js +184 -0
  38. package/dist/plugin/trigger-hook.js.map +1 -0
  39. package/dist/steps/create-step.d.ts +66 -0
  40. package/dist/steps/create-step.js +59 -0
  41. package/dist/steps/create-step.js.map +1 -0
  42. package/dist/steps/index.d.ts +2 -0
  43. package/dist/steps/index.js +3 -0
  44. package/dist/steps/index.js.map +1 -1
  45. package/dist/steps/read-document-handler.js +1 -1
  46. package/dist/steps/read-document-handler.js.map +1 -1
  47. package/dist/steps/update-document-handler.js +1 -1
  48. package/dist/steps/update-document-handler.js.map +1 -1
  49. package/dist/triggers/hook-options.d.ts +34 -0
  50. package/dist/triggers/hook-options.js +158 -0
  51. package/dist/triggers/hook-options.js.map +1 -0
  52. package/dist/triggers/index.d.ts +2 -2
  53. package/dist/triggers/index.js +1 -2
  54. package/dist/triggers/index.js.map +1 -1
  55. package/dist/types/index.d.ts +8 -0
  56. package/dist/types/index.js +4 -5
  57. package/dist/types/index.js.map +1 -1
  58. package/dist/utils/validation.d.ts +64 -0
  59. package/dist/utils/validation.js +107 -0
  60. package/dist/utils/validation.js.map +1 -0
  61. package/package.json +2 -1
  62. package/dist/plugin/collection-hook.d.ts +0 -1
  63. package/dist/plugin/collection-hook.js +0 -92
  64. package/dist/plugin/collection-hook.js.map +0 -1
  65. package/dist/plugin/global-hook.d.ts +0 -1
  66. package/dist/plugin/global-hook.js +0 -83
  67. package/dist/plugin/global-hook.js.map +0 -1
  68. package/dist/triggers/collection-trigger.d.ts +0 -2
  69. package/dist/triggers/collection-trigger.js +0 -36
  70. package/dist/triggers/collection-trigger.js.map +0 -1
  71. package/dist/triggers/global-trigger.d.ts +0 -2
  72. package/dist/triggers/global-trigger.js +0 -29
  73. package/dist/triggers/global-trigger.js.map +0 -1
  74. package/dist/triggers/types.d.ts +0 -5
  75. package/dist/triggers/types.js +0 -3
  76. package/dist/triggers/types.js.map +0 -1
@@ -0,0 +1,224 @@
1
+ import { collectionHookOptions } from '../triggers/hook-options.js';
2
+ /**
3
+ * Creates the automation-triggers collection.
4
+ * Triggers are reusable and can be shared across multiple workflows.
5
+ */ export const createTriggersCollection = (options)=>{
6
+ const collectionSlugs = Object.keys(options.collectionTriggers || {});
7
+ const globalSlugs = Object.keys(options.globalTriggers || {});
8
+ return {
9
+ slug: 'automation-triggers',
10
+ access: {
11
+ create: ()=>true,
12
+ delete: ()=>true,
13
+ read: ()=>true,
14
+ update: ()=>true
15
+ },
16
+ admin: {
17
+ defaultColumns: [
18
+ 'name',
19
+ 'type',
20
+ 'target',
21
+ 'updatedAt'
22
+ ],
23
+ description: 'Reusable trigger definitions that can be shared across workflows.',
24
+ group: 'Automation',
25
+ useAsTitle: 'name'
26
+ },
27
+ fields: [
28
+ {
29
+ name: 'name',
30
+ type: 'text',
31
+ admin: {
32
+ description: 'Human-readable name for this trigger'
33
+ },
34
+ required: true
35
+ },
36
+ {
37
+ name: 'description',
38
+ type: 'textarea',
39
+ admin: {
40
+ description: 'Optional description of when this trigger fires'
41
+ }
42
+ },
43
+ {
44
+ name: 'type',
45
+ type: 'select',
46
+ admin: {
47
+ description: 'The type of event that will fire this trigger'
48
+ },
49
+ defaultValue: 'collection-hook',
50
+ options: [
51
+ {
52
+ label: 'Collection Hook',
53
+ value: 'collection-hook'
54
+ },
55
+ {
56
+ label: 'Global Hook',
57
+ value: 'global-hook'
58
+ },
59
+ {
60
+ label: 'Scheduled (Cron)',
61
+ value: 'scheduled'
62
+ },
63
+ {
64
+ label: 'Webhook',
65
+ value: 'webhook'
66
+ },
67
+ {
68
+ label: 'Manual',
69
+ value: 'manual'
70
+ }
71
+ ],
72
+ required: true
73
+ },
74
+ // Virtual field to show human-readable target
75
+ {
76
+ name: 'target',
77
+ type: 'text',
78
+ admin: {
79
+ readOnly: true,
80
+ description: 'The target of this trigger'
81
+ },
82
+ hooks: {
83
+ beforeChange: [
84
+ ({ siblingData })=>{
85
+ // Compute target based on type
86
+ if (siblingData.type === 'collection-hook') {
87
+ return `${siblingData.collectionSlug}.${siblingData.hook}`;
88
+ } else if (siblingData.type === 'global-hook') {
89
+ return `${siblingData.globalSlug}.${siblingData.hook}`;
90
+ } else if (siblingData.type === 'scheduled') {
91
+ return siblingData.schedule || 'Not configured';
92
+ } else if (siblingData.type === 'webhook') {
93
+ return siblingData.webhookPath || 'Not configured';
94
+ }
95
+ return 'Manual trigger';
96
+ }
97
+ ]
98
+ }
99
+ },
100
+ // Collection Hook fields
101
+ {
102
+ name: 'collectionSlug',
103
+ type: 'select',
104
+ admin: {
105
+ condition: (_, siblingData)=>siblingData?.type === 'collection-hook',
106
+ description: 'The collection to watch for events'
107
+ },
108
+ options: collectionSlugs.map((slug)=>({
109
+ label: slug,
110
+ value: slug
111
+ }))
112
+ },
113
+ {
114
+ name: 'hook',
115
+ type: 'select',
116
+ admin: {
117
+ condition: (_, siblingData)=>siblingData?.type === 'collection-hook' || siblingData?.type === 'global-hook',
118
+ description: 'The specific hook event to listen for'
119
+ },
120
+ options: collectionHookOptions.map((opt)=>({
121
+ label: opt.label,
122
+ value: opt.value
123
+ }))
124
+ },
125
+ // Global Hook fields
126
+ {
127
+ name: 'globalSlug',
128
+ type: 'select',
129
+ admin: {
130
+ condition: (_, siblingData)=>siblingData?.type === 'global-hook',
131
+ description: 'The global to watch for events'
132
+ },
133
+ options: globalSlugs.map((slug)=>({
134
+ label: slug,
135
+ value: slug
136
+ }))
137
+ },
138
+ // Scheduled fields
139
+ {
140
+ name: 'schedule',
141
+ type: 'text',
142
+ admin: {
143
+ condition: (_, siblingData)=>siblingData?.type === 'scheduled',
144
+ description: 'Cron expression (e.g., "0 9 * * *" for 9 AM daily)',
145
+ placeholder: '0 9 * * *'
146
+ }
147
+ },
148
+ // Webhook fields
149
+ {
150
+ name: 'webhookPath',
151
+ type: 'text',
152
+ admin: {
153
+ condition: (_, siblingData)=>siblingData?.type === 'webhook',
154
+ description: 'The URL path for this webhook (e.g., "my-webhook")',
155
+ placeholder: 'my-webhook'
156
+ }
157
+ },
158
+ // Condition configuration
159
+ {
160
+ type: 'collapsible',
161
+ label: 'Condition',
162
+ admin: {
163
+ initCollapsed: true
164
+ },
165
+ fields: [
166
+ {
167
+ name: 'condition',
168
+ type: 'code',
169
+ admin: {
170
+ description: 'JSONata expression that must evaluate to true for this trigger to fire. Leave empty to always fire. Example: trigger.doc._status = "published"',
171
+ language: 'javascript'
172
+ }
173
+ },
174
+ {
175
+ name: 'conditionDescription',
176
+ type: 'text',
177
+ admin: {
178
+ description: 'Human-readable explanation of the condition (for documentation)',
179
+ placeholder: 'e.g., "Only when status is published"'
180
+ }
181
+ }
182
+ ]
183
+ },
184
+ // Usage tracking
185
+ {
186
+ name: 'usageCount',
187
+ type: 'number',
188
+ admin: {
189
+ description: 'Number of workflows using this trigger',
190
+ readOnly: true,
191
+ position: 'sidebar'
192
+ },
193
+ defaultValue: 0
194
+ }
195
+ ],
196
+ hooks: {
197
+ beforeChange: [
198
+ // Validate required fields based on type
199
+ async ({ data, operation })=>{
200
+ if (operation === 'create' || operation === 'update') {
201
+ if (data?.type === 'collection-hook' && !data?.collectionSlug) {
202
+ throw new Error('Collection is required for collection hook triggers');
203
+ }
204
+ if (data?.type === 'global-hook' && !data?.globalSlug) {
205
+ throw new Error('Global is required for global hook triggers');
206
+ }
207
+ if ((data?.type === 'collection-hook' || data?.type === 'global-hook') && !data?.hook) {
208
+ throw new Error('Hook type is required');
209
+ }
210
+ if (data?.type === 'scheduled' && !data?.schedule) {
211
+ throw new Error('Schedule is required for scheduled triggers');
212
+ }
213
+ if (data?.type === 'webhook' && !data?.webhookPath) {
214
+ throw new Error('Webhook path is required for webhook triggers');
215
+ }
216
+ }
217
+ return data;
218
+ }
219
+ ]
220
+ }
221
+ };
222
+ };
223
+
224
+ //# sourceMappingURL=Triggers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/collections/Triggers.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { WorkflowsPluginConfig } from '../plugin/config-types.js'\n\nimport { collectionHookOptions, globalHookOptions } from '../triggers/hook-options.js'\n\n/**\n * Creates the automation-triggers collection.\n * Triggers are reusable and can be shared across multiple workflows.\n */\nexport const createTriggersCollection = <T extends string>(\n options: WorkflowsPluginConfig<T>\n): CollectionConfig => {\n const collectionSlugs = Object.keys(options.collectionTriggers || {})\n const globalSlugs = Object.keys(options.globalTriggers || {})\n\n return {\n slug: 'automation-triggers',\n access: {\n create: () => true,\n delete: () => true,\n read: () => true,\n update: () => true,\n },\n admin: {\n defaultColumns: ['name', 'type', 'target', 'updatedAt'],\n description: 'Reusable trigger definitions that can be shared across 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 this trigger',\n },\n required: true,\n },\n {\n name: 'description',\n type: 'textarea',\n admin: {\n description: 'Optional description of when this trigger fires',\n },\n },\n {\n name: 'type',\n type: 'select',\n admin: {\n description: 'The type of event that will fire this trigger',\n },\n defaultValue: 'collection-hook',\n options: [\n { label: 'Collection Hook', value: 'collection-hook' },\n { label: 'Global Hook', value: 'global-hook' },\n { label: 'Scheduled (Cron)', value: 'scheduled' },\n { label: 'Webhook', value: 'webhook' },\n { label: 'Manual', value: 'manual' },\n ],\n required: true,\n },\n // Virtual field to show human-readable target\n {\n name: 'target',\n type: 'text',\n admin: {\n readOnly: true,\n description: 'The target of this trigger',\n },\n hooks: {\n beforeChange: [\n ({ siblingData }) => {\n // Compute target based on type\n if (siblingData.type === 'collection-hook') {\n return `${siblingData.collectionSlug}.${siblingData.hook}`\n } else if (siblingData.type === 'global-hook') {\n return `${siblingData.globalSlug}.${siblingData.hook}`\n } else if (siblingData.type === 'scheduled') {\n return siblingData.schedule || 'Not configured'\n } else if (siblingData.type === 'webhook') {\n return siblingData.webhookPath || 'Not configured'\n }\n return 'Manual trigger'\n }\n ]\n }\n },\n // Collection Hook fields\n {\n name: 'collectionSlug',\n type: 'select',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'collection-hook',\n description: 'The collection to watch for events',\n },\n options: collectionSlugs.map(slug => ({ label: slug, value: slug })),\n },\n {\n name: 'hook',\n type: 'select',\n admin: {\n condition: (_, siblingData) =>\n siblingData?.type === 'collection-hook' || siblingData?.type === 'global-hook',\n description: 'The specific hook event to listen for',\n },\n options: collectionHookOptions.map(opt => ({ label: opt.label, value: opt.value })),\n },\n // Global Hook fields\n {\n name: 'globalSlug',\n type: 'select',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'global-hook',\n description: 'The global to watch for events',\n },\n options: globalSlugs.map(slug => ({ label: slug, value: slug })),\n },\n // Scheduled fields\n {\n name: 'schedule',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'scheduled',\n description: 'Cron expression (e.g., \"0 9 * * *\" for 9 AM daily)',\n placeholder: '0 9 * * *',\n },\n },\n // Webhook fields\n {\n name: 'webhookPath',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'webhook',\n description: 'The URL path for this webhook (e.g., \"my-webhook\")',\n placeholder: 'my-webhook',\n },\n },\n // Condition configuration\n {\n type: 'collapsible',\n label: 'Condition',\n admin: {\n initCollapsed: true,\n },\n fields: [\n {\n name: 'condition',\n type: 'code',\n admin: {\n description: 'JSONata expression that must evaluate to true for this trigger to fire. Leave empty to always fire. Example: trigger.doc._status = \"published\"',\n language: 'javascript',\n },\n },\n {\n name: 'conditionDescription',\n type: 'text',\n admin: {\n description: 'Human-readable explanation of the condition (for documentation)',\n placeholder: 'e.g., \"Only when status is published\"',\n },\n },\n ],\n },\n // Usage tracking\n {\n name: 'usageCount',\n type: 'number',\n admin: {\n description: 'Number of workflows using this trigger',\n readOnly: true,\n position: 'sidebar',\n },\n defaultValue: 0,\n },\n ],\n hooks: {\n beforeChange: [\n // Validate required fields based on type\n async ({ data, operation }) => {\n if (operation === 'create' || operation === 'update') {\n if (data?.type === 'collection-hook' && !data?.collectionSlug) {\n throw new Error('Collection is required for collection hook triggers')\n }\n if (data?.type === 'global-hook' && !data?.globalSlug) {\n throw new Error('Global is required for global hook triggers')\n }\n if ((data?.type === 'collection-hook' || data?.type === 'global-hook') && !data?.hook) {\n throw new Error('Hook type is required')\n }\n if (data?.type === 'scheduled' && !data?.schedule) {\n throw new Error('Schedule is required for scheduled triggers')\n }\n if (data?.type === 'webhook' && !data?.webhookPath) {\n throw new Error('Webhook path is required for webhook triggers')\n }\n }\n return data\n }\n ],\n },\n }\n}\n"],"names":["collectionHookOptions","createTriggersCollection","options","collectionSlugs","Object","keys","collectionTriggers","globalSlugs","globalTriggers","slug","access","create","delete","read","update","admin","defaultColumns","description","group","useAsTitle","fields","name","type","required","defaultValue","label","value","readOnly","hooks","beforeChange","siblingData","collectionSlug","hook","globalSlug","schedule","webhookPath","condition","_","map","opt","placeholder","initCollapsed","language","position","data","operation","Error"],"mappings":"AAIA,SAASA,qBAAqB,QAA2B,8BAA6B;AAEtF;;;CAGC,GACD,OAAO,MAAMC,2BAA2B,CACtCC;IAEA,MAAMC,kBAAkBC,OAAOC,IAAI,CAACH,QAAQI,kBAAkB,IAAI,CAAC;IACnE,MAAMC,cAAcH,OAAOC,IAAI,CAACH,QAAQM,cAAc,IAAI,CAAC;IAE3D,OAAO;QACLC,MAAM;QACNC,QAAQ;YACNC,QAAQ,IAAM;YACdC,QAAQ,IAAM;YACdC,MAAM,IAAM;YACZC,QAAQ,IAAM;QAChB;QACAC,OAAO;YACLC,gBAAgB;gBAAC;gBAAQ;gBAAQ;gBAAU;aAAY;YACvDC,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;gBACf;YACF;YACA;gBACEI,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;gBACf;gBACAO,cAAc;gBACdtB,SAAS;oBACP;wBAAEuB,OAAO;wBAAmBC,OAAO;oBAAkB;oBACrD;wBAAED,OAAO;wBAAeC,OAAO;oBAAc;oBAC7C;wBAAED,OAAO;wBAAoBC,OAAO;oBAAY;oBAChD;wBAAED,OAAO;wBAAWC,OAAO;oBAAU;oBACrC;wBAAED,OAAO;wBAAUC,OAAO;oBAAS;iBACpC;gBACDH,UAAU;YACZ;YACA,8CAA8C;YAC9C;gBACEF,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLY,UAAU;oBACVV,aAAa;gBACf;gBACAW,OAAO;oBACLC,cAAc;wBACZ,CAAC,EAAEC,WAAW,EAAE;4BACd,+BAA+B;4BAC/B,IAAIA,YAAYR,IAAI,KAAK,mBAAmB;gCAC1C,OAAO,GAAGQ,YAAYC,cAAc,CAAC,CAAC,EAAED,YAAYE,IAAI,EAAE;4BAC5D,OAAO,IAAIF,YAAYR,IAAI,KAAK,eAAe;gCAC7C,OAAO,GAAGQ,YAAYG,UAAU,CAAC,CAAC,EAAEH,YAAYE,IAAI,EAAE;4BACxD,OAAO,IAAIF,YAAYR,IAAI,KAAK,aAAa;gCAC3C,OAAOQ,YAAYI,QAAQ,IAAI;4BACjC,OAAO,IAAIJ,YAAYR,IAAI,KAAK,WAAW;gCACzC,OAAOQ,YAAYK,WAAW,IAAI;4BACpC;4BACA,OAAO;wBACT;qBACD;gBACH;YACF;YACA,yBAAyB;YACzB;gBACEd,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLqB,WAAW,CAACC,GAAGP,cAAgBA,aAAaR,SAAS;oBACrDL,aAAa;gBACf;gBACAf,SAASC,gBAAgBmC,GAAG,CAAC7B,CAAAA,OAAS,CAAA;wBAAEgB,OAAOhB;wBAAMiB,OAAOjB;oBAAK,CAAA;YACnE;YACA;gBACEY,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLqB,WAAW,CAACC,GAAGP,cACbA,aAAaR,SAAS,qBAAqBQ,aAAaR,SAAS;oBACnEL,aAAa;gBACf;gBACAf,SAASF,sBAAsBsC,GAAG,CAACC,CAAAA,MAAQ,CAAA;wBAAEd,OAAOc,IAAId,KAAK;wBAAEC,OAAOa,IAAIb,KAAK;oBAAC,CAAA;YAClF;YACA,qBAAqB;YACrB;gBACEL,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLqB,WAAW,CAACC,GAAGP,cAAgBA,aAAaR,SAAS;oBACrDL,aAAa;gBACf;gBACAf,SAASK,YAAY+B,GAAG,CAAC7B,CAAAA,OAAS,CAAA;wBAAEgB,OAAOhB;wBAAMiB,OAAOjB;oBAAK,CAAA;YAC/D;YACA,mBAAmB;YACnB;gBACEY,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLqB,WAAW,CAACC,GAAGP,cAAgBA,aAAaR,SAAS;oBACrDL,aAAa;oBACbuB,aAAa;gBACf;YACF;YACA,iBAAiB;YACjB;gBACEnB,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLqB,WAAW,CAACC,GAAGP,cAAgBA,aAAaR,SAAS;oBACrDL,aAAa;oBACbuB,aAAa;gBACf;YACF;YACA,0BAA0B;YAC1B;gBACElB,MAAM;gBACNG,OAAO;gBACPV,OAAO;oBACL0B,eAAe;gBACjB;gBACArB,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;4BACbyB,UAAU;wBACZ;oBACF;oBACA;wBACErB,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;4BACbuB,aAAa;wBACf;oBACF;iBACD;YACH;YACA,iBAAiB;YACjB;gBACEnB,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;oBACbU,UAAU;oBACVgB,UAAU;gBACZ;gBACAnB,cAAc;YAChB;SACD;QACDI,OAAO;YACLC,cAAc;gBACZ,yCAAyC;gBACzC,OAAO,EAAEe,IAAI,EAAEC,SAAS,EAAE;oBACxB,IAAIA,cAAc,YAAYA,cAAc,UAAU;wBACpD,IAAID,MAAMtB,SAAS,qBAAqB,CAACsB,MAAMb,gBAAgB;4BAC7D,MAAM,IAAIe,MAAM;wBAClB;wBACA,IAAIF,MAAMtB,SAAS,iBAAiB,CAACsB,MAAMX,YAAY;4BACrD,MAAM,IAAIa,MAAM;wBAClB;wBACA,IAAI,AAACF,CAAAA,MAAMtB,SAAS,qBAAqBsB,MAAMtB,SAAS,aAAY,KAAM,CAACsB,MAAMZ,MAAM;4BACrF,MAAM,IAAIc,MAAM;wBAClB;wBACA,IAAIF,MAAMtB,SAAS,eAAe,CAACsB,MAAMV,UAAU;4BACjD,MAAM,IAAIY,MAAM;wBAClB;wBACA,IAAIF,MAAMtB,SAAS,aAAa,CAACsB,MAAMT,aAAa;4BAClD,MAAM,IAAIW,MAAM;wBAClB;oBACF;oBACA,OAAOF;gBACT;aACD;QACH;IACF;AACF,EAAC"}
@@ -1,3 +1,6 @@
1
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;
2
+ /**
3
+ * Creates the workflows collection.
4
+ * Workflows reference triggers and steps via relationships for reusability.
5
+ */
6
+ export declare const createWorkflowCollection: () => CollectionConfig;
@@ -1,8 +1,7 @@
1
- import { parameter } from "../fields/parameter.js";
2
- import { collectionTrigger, globalTrigger } from "../triggers/index.js";
3
- export const createWorkflowCollection = (options)=>{
4
- const steps = options.steps || [];
5
- const triggers = (options.triggers || []).map((t)=>t(options)).concat(collectionTrigger(options), globalTrigger(options));
1
+ /**
2
+ * Creates the workflows collection.
3
+ * Workflows reference triggers and steps via relationships for reusability.
4
+ */ export const createWorkflowCollection = ()=>{
6
5
  return {
7
6
  slug: 'workflows',
8
7
  access: {
@@ -28,6 +27,7 @@ export const createWorkflowCollection = (options)=>{
28
27
  'name',
29
28
  'slug',
30
29
  'readOnly',
30
+ 'enabled',
31
31
  'updatedAt'
32
32
  ],
33
33
  description: 'Create and manage automated workflows.',
@@ -80,79 +80,219 @@ export const createWorkflowCollection = (options)=>{
80
80
  description: 'Optional description of what this workflow does'
81
81
  }
82
82
  },
83
+ {
84
+ name: 'enabled',
85
+ type: 'checkbox',
86
+ admin: {
87
+ description: 'Enable or disable this workflow',
88
+ position: 'sidebar'
89
+ },
90
+ defaultValue: true
91
+ },
92
+ // Triggers - relationship to automation-triggers collection
83
93
  {
84
94
  name: 'triggers',
95
+ type: 'relationship',
96
+ admin: {
97
+ description: 'Triggers that can start this workflow. Uses OR logic - workflow runs if ANY trigger fires.'
98
+ },
99
+ hasMany: true,
100
+ relationTo: 'automation-triggers'
101
+ },
102
+ // Steps with workflow-specific configuration
103
+ {
104
+ name: 'steps',
85
105
  type: 'array',
106
+ admin: {
107
+ description: 'Steps to execute when this workflow runs. Steps execute in order based on dependencies.'
108
+ },
86
109
  fields: [
87
110
  {
88
- name: 'type',
89
- type: 'select',
90
- options: [
91
- ...triggers.map((t)=>t.slug)
92
- ]
111
+ name: 'step',
112
+ type: 'relationship',
113
+ admin: {
114
+ description: 'Select a step from the step library'
115
+ },
116
+ relationTo: 'automation-steps',
117
+ required: true
93
118
  },
94
119
  {
95
- name: 'parameters',
120
+ name: 'stepName',
121
+ type: 'text',
122
+ admin: {
123
+ description: 'Override the step name for this workflow instance (optional)'
124
+ }
125
+ },
126
+ {
127
+ name: 'inputOverrides',
96
128
  type: 'json',
97
129
  admin: {
98
- hidden: true
130
+ description: 'Override step configuration values for this workflow. Merged with step defaults.'
99
131
  },
100
132
  defaultValue: {}
101
133
  },
102
- // Virtual fields for custom triggers
103
- ...triggers.flatMap((t)=>(t.parameters || []).map((p)=>parameter(t.slug, p))),
104
134
  {
105
135
  name: 'condition',
106
- type: 'text',
136
+ type: 'code',
137
+ admin: {
138
+ description: 'JSONata expression that must evaluate to true for this step to execute. Leave empty to always run. Example: trigger.operation = "create"',
139
+ language: 'javascript'
140
+ }
141
+ },
142
+ {
143
+ name: 'dependencies',
144
+ type: 'array',
107
145
  admin: {
108
- description: 'JSONPath expression that must evaluate to true for this trigger to execute the workflow (e.g., "$.trigger.doc.status == \'published\'")'
146
+ description: 'Steps that must complete before this step can run'
109
147
  },
110
- required: false
148
+ fields: [
149
+ {
150
+ name: 'stepIndex',
151
+ type: 'number',
152
+ admin: {
153
+ description: 'Index of the dependent step (0-based)'
154
+ },
155
+ required: true
156
+ }
157
+ ]
158
+ },
159
+ // Visual builder position
160
+ {
161
+ name: 'position',
162
+ type: 'point',
163
+ admin: {
164
+ description: 'Position in the visual workflow builder',
165
+ hidden: true
166
+ }
111
167
  }
112
168
  ]
113
169
  },
170
+ // Global workflow settings
114
171
  {
115
- name: 'steps',
116
- type: 'array',
172
+ type: 'collapsible',
173
+ label: 'Error Handling',
174
+ admin: {
175
+ initCollapsed: true
176
+ },
117
177
  fields: [
118
178
  {
119
- name: 'name',
120
- type: 'text',
121
- defaultValue: 'Unnamed Step'
122
- },
123
- {
124
- name: 'type',
179
+ name: 'errorHandling',
125
180
  type: 'select',
126
- options: steps.map((t)=>t.slug)
181
+ admin: {
182
+ description: 'How to handle step failures'
183
+ },
184
+ defaultValue: 'stop',
185
+ options: [
186
+ {
187
+ label: 'Stop workflow',
188
+ value: 'stop'
189
+ },
190
+ {
191
+ label: 'Continue to next step',
192
+ value: 'continue'
193
+ },
194
+ {
195
+ label: 'Retry failed step',
196
+ value: 'retry'
197
+ }
198
+ ]
127
199
  },
128
200
  {
129
- name: 'input',
130
- type: 'json',
201
+ name: 'maxRetries',
202
+ type: 'number',
131
203
  admin: {
132
- description: 'Step input configuration. Use JSONPath expressions to reference dynamic data (e.g., {"url": "$.trigger.doc.webhookUrl", "data": "$.steps.previousStep.output.result"})'
204
+ condition: (_, siblingData)=>siblingData?.errorHandling === 'retry',
205
+ description: 'Maximum number of retry attempts'
133
206
  },
134
- defaultValue: {}
207
+ defaultValue: 3
135
208
  },
136
209
  {
137
- name: 'dependencies',
138
- type: 'text',
210
+ name: 'retryDelay',
211
+ type: 'number',
139
212
  admin: {
140
- description: 'Step names that must complete before this step can run'
213
+ condition: (_, siblingData)=>siblingData?.errorHandling === 'retry',
214
+ description: 'Delay between retries in milliseconds'
141
215
  },
142
- hasMany: true,
143
- required: false
216
+ defaultValue: 1000
144
217
  },
145
218
  {
146
- name: 'condition',
147
- type: 'text',
219
+ name: 'timeout',
220
+ type: 'number',
148
221
  admin: {
149
- description: 'JSONPath expression that must evaluate to true for this step to execute (e.g., "$.trigger.doc.status == \'published\'")'
222
+ description: 'Maximum execution time in milliseconds (0 for no timeout)'
150
223
  },
151
- required: false
224
+ defaultValue: 300000
152
225
  }
153
226
  ]
154
227
  }
155
228
  ],
229
+ hooks: {
230
+ afterChange: [
231
+ // Update usage counts for triggers and steps
232
+ async ({ doc, req })=>{
233
+ const payload = req.payload;
234
+ // Update trigger usage counts
235
+ if (doc.triggers && Array.isArray(doc.triggers)) {
236
+ for (const triggerId of doc.triggers){
237
+ const id = typeof triggerId === 'object' ? triggerId.id : triggerId;
238
+ if (id) {
239
+ try {
240
+ // Count workflows using this trigger
241
+ const count = await payload.count({
242
+ collection: 'workflows',
243
+ where: {
244
+ triggers: {
245
+ contains: id
246
+ }
247
+ }
248
+ });
249
+ await payload.update({
250
+ collection: 'automation-triggers',
251
+ id,
252
+ data: {
253
+ usageCount: count.totalDocs
254
+ }
255
+ });
256
+ } catch {
257
+ // Ignore errors - trigger might have been deleted
258
+ }
259
+ }
260
+ }
261
+ }
262
+ // Update step usage counts
263
+ if (doc.steps && Array.isArray(doc.steps)) {
264
+ const stepIds = new Set();
265
+ for (const workflowStep of doc.steps){
266
+ const stepId = typeof workflowStep.step === 'object' ? workflowStep.step.id : workflowStep.step;
267
+ if (stepId) stepIds.add(stepId);
268
+ }
269
+ for (const stepId of stepIds){
270
+ try {
271
+ // Count workflows using this step
272
+ const count = await payload.count({
273
+ collection: 'workflows',
274
+ where: {
275
+ 'steps.step': {
276
+ equals: stepId
277
+ }
278
+ }
279
+ });
280
+ await payload.update({
281
+ collection: 'automation-steps',
282
+ id: stepId,
283
+ data: {
284
+ usageCount: count.totalDocs
285
+ }
286
+ });
287
+ } catch {
288
+ // Ignore errors - step might have been deleted
289
+ }
290
+ }
291
+ }
292
+ return doc;
293
+ }
294
+ ]
295
+ },
156
296
  versions: {
157
297
  drafts: {
158
298
  autosave: false
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/collections/Workflow.ts"],"sourcesContent":["import type {CollectionConfig} from 'payload'\n\nimport type {WorkflowsPluginConfig} from \"../plugin/config-types.js\"\n\nimport {parameter} from \"../fields/parameter.js\"\nimport {collectionTrigger, globalTrigger} from \"../triggers/index.js\"\n\nexport const createWorkflowCollection: <T extends string>(options: WorkflowsPluginConfig<T>) => CollectionConfig = (options) => {\n const steps = options.steps || []\n const triggers = (options.triggers || []).map(t => t(options)).concat(collectionTrigger(options), globalTrigger(options))\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', '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: 'triggers',\n type: 'array',\n fields: [\n {\n name: 'type',\n type: 'select',\n options: [\n ...triggers.map(t => t.slug)\n ]\n },\n {\n name: 'parameters',\n type: 'json',\n admin: {\n hidden: true,\n },\n defaultValue: {}\n },\n // Virtual fields for custom triggers\n ...triggers.flatMap(t => (t.parameters || []).map(p => parameter(t.slug, p as any))),\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., \"$.trigger.doc.status == \\'published\\'\")'\n },\n required: false\n },\n ]\n },\n {\n name: 'steps',\n type: 'array',\n fields: [\n {\n name: 'name',\n type: 'text',\n defaultValue: 'Unnamed Step'\n },\n {\n name: 'type',\n type: 'select',\n options: steps.map(t => t.slug)\n },\n {\n name: 'input',\n type: 'json',\n admin: {\n description: 'Step input configuration. Use JSONPath expressions to reference dynamic data (e.g., {\"url\": \"$.trigger.doc.webhookUrl\", \"data\": \"$.steps.previousStep.output.result\"})'\n },\n defaultValue: {}\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}\n"],"names":["parameter","collectionTrigger","globalTrigger","createWorkflowCollection","options","steps","triggers","map","t","concat","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","hidden","flatMap","parameters","p","hasMany","versions","drafts","autosave","maxPerDoc"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/collections/Workflow.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\n/**\n * Creates the workflows collection.\n * Workflows reference triggers and steps via relationships for reusability.\n */\nexport const createWorkflowCollection = (): CollectionConfig => {\n return {\n slug: 'workflows',\n access: {\n create: () => true,\n delete: ({ req, data }) => {\n // Prevent deletion of read-only workflows\n if (data?.readOnly === true) {\n return false\n }\n return true\n },\n read: () => true,\n update: ({ req, data }) => {\n // Prevent updates to read-only workflows\n if (data?.readOnly === true) {\n return false\n }\n return true\n },\n },\n admin: {\n defaultColumns: ['name', 'slug', 'readOnly', 'enabled', 'updatedAt'],\n description: 'Create and manage automated workflows.',\n group: 'Automation',\n useAsTitle: 'name',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n admin: {\n description: 'Human-readable name for the workflow',\n },\n required: true,\n },\n {\n name: 'slug',\n type: 'text',\n admin: {\n description: 'URL-safe unique identifier for this workflow',\n position: 'sidebar',\n },\n index: true,\n unique: true,\n },\n {\n name: 'readOnly',\n type: 'checkbox',\n admin: {\n description: 'Read-only workflows cannot be edited or deleted. This is typically used for seeded template workflows.',\n position: 'sidebar',\n readOnly: true,\n },\n defaultValue: false,\n },\n {\n name: 'readOnlyBanner',\n type: 'ui',\n admin: {\n components: {\n Field: '@xtr-dev/payload-automation/client#ReadOnlyBanner',\n },\n condition: (data) => data?.readOnly === true,\n },\n },\n {\n name: 'description',\n type: 'textarea',\n admin: {\n description: 'Optional description of what this workflow does',\n },\n },\n {\n name: 'enabled',\n type: 'checkbox',\n admin: {\n description: 'Enable or disable this workflow',\n position: 'sidebar',\n },\n defaultValue: true,\n },\n // Triggers - relationship to automation-triggers collection\n {\n name: 'triggers',\n type: 'relationship',\n admin: {\n description: 'Triggers that can start this workflow. Uses OR logic - workflow runs if ANY trigger fires.',\n },\n hasMany: true,\n relationTo: 'automation-triggers',\n },\n // Steps with workflow-specific configuration\n {\n name: 'steps',\n type: 'array',\n admin: {\n description: 'Steps to execute when this workflow runs. Steps execute in order based on dependencies.',\n },\n fields: [\n {\n name: 'step',\n type: 'relationship',\n admin: {\n description: 'Select a step from the step library',\n },\n relationTo: 'automation-steps',\n required: true,\n },\n {\n name: 'stepName',\n type: 'text',\n admin: {\n description: 'Override the step name for this workflow instance (optional)',\n },\n },\n {\n name: 'inputOverrides',\n type: 'json',\n admin: {\n description: 'Override step configuration values for this workflow. Merged with step defaults.',\n },\n defaultValue: {},\n },\n {\n name: 'condition',\n type: 'code',\n admin: {\n description: 'JSONata expression that must evaluate to true for this step to execute. Leave empty to always run. Example: trigger.operation = \"create\"',\n language: 'javascript',\n },\n },\n {\n name: 'dependencies',\n type: 'array',\n admin: {\n description: 'Steps that must complete before this step can run',\n },\n fields: [\n {\n name: 'stepIndex',\n type: 'number',\n admin: {\n description: 'Index of the dependent step (0-based)',\n },\n required: true,\n },\n ],\n },\n // Visual builder position\n {\n name: 'position',\n type: 'point',\n admin: {\n description: 'Position in the visual workflow builder',\n hidden: true,\n },\n },\n ],\n },\n // Global workflow settings\n {\n type: 'collapsible',\n label: 'Error Handling',\n admin: {\n initCollapsed: true,\n },\n fields: [\n {\n name: 'errorHandling',\n type: 'select',\n admin: {\n description: 'How to handle step failures',\n },\n defaultValue: 'stop',\n options: [\n { label: 'Stop workflow', value: 'stop' },\n { label: 'Continue to next step', value: 'continue' },\n { label: 'Retry failed step', value: 'retry' },\n ],\n },\n {\n name: 'maxRetries',\n type: 'number',\n admin: {\n condition: (_, siblingData) => siblingData?.errorHandling === 'retry',\n description: 'Maximum number of retry attempts',\n },\n defaultValue: 3,\n },\n {\n name: 'retryDelay',\n type: 'number',\n admin: {\n condition: (_, siblingData) => siblingData?.errorHandling === 'retry',\n description: 'Delay between retries in milliseconds',\n },\n defaultValue: 1000,\n },\n {\n name: 'timeout',\n type: 'number',\n admin: {\n description: 'Maximum execution time in milliseconds (0 for no timeout)',\n },\n defaultValue: 300000, // 5 minutes\n },\n ],\n },\n ],\n hooks: {\n afterChange: [\n // Update usage counts for triggers and steps\n async ({ doc, req }) => {\n const payload = req.payload\n\n // Update trigger usage counts\n if (doc.triggers && Array.isArray(doc.triggers)) {\n for (const triggerId of doc.triggers) {\n const id = typeof triggerId === 'object' ? triggerId.id : triggerId\n if (id) {\n try {\n // Count workflows using this trigger\n const count = await payload.count({\n collection: 'workflows',\n where: {\n triggers: { contains: id },\n },\n })\n await payload.update({\n collection: 'automation-triggers',\n id,\n data: { usageCount: count.totalDocs },\n })\n } catch {\n // Ignore errors - trigger might have been deleted\n }\n }\n }\n }\n\n // Update step usage counts\n if (doc.steps && Array.isArray(doc.steps)) {\n const stepIds = new Set<string>()\n for (const workflowStep of doc.steps) {\n const stepId = typeof workflowStep.step === 'object'\n ? workflowStep.step.id\n : workflowStep.step\n if (stepId) stepIds.add(stepId)\n }\n\n for (const stepId of stepIds) {\n try {\n // Count workflows using this step\n const count = await payload.count({\n collection: 'workflows',\n where: {\n 'steps.step': { equals: stepId },\n },\n })\n await payload.update({\n collection: 'automation-steps',\n id: stepId,\n data: { usageCount: count.totalDocs },\n })\n } catch {\n // Ignore errors - step might have been deleted\n }\n }\n }\n\n return doc\n },\n ],\n },\n versions: {\n drafts: {\n autosave: false,\n },\n maxPerDoc: 10,\n },\n }\n}\n"],"names":["createWorkflowCollection","slug","access","create","delete","req","data","readOnly","read","update","admin","defaultColumns","description","group","useAsTitle","fields","name","type","required","position","index","unique","defaultValue","components","Field","condition","hasMany","relationTo","language","hidden","label","initCollapsed","options","value","_","siblingData","errorHandling","hooks","afterChange","doc","payload","triggers","Array","isArray","triggerId","id","count","collection","where","contains","usageCount","totalDocs","steps","stepIds","Set","workflowStep","stepId","step","add","equals","versions","drafts","autosave","maxPerDoc"],"mappings":"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"}
@@ -1,2 +1,6 @@
1
1
  import type { CollectionConfig } from 'payload';
2
+ /**
3
+ * WorkflowRuns collection for tracking workflow executions.
4
+ * Enhanced with structured step results and trigger tracking.
5
+ */
2
6
  export declare const WorkflowRunsCollection: CollectionConfig;