@xtr-dev/payload-automation 0.0.39 → 0.0.42

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 (57) hide show
  1. package/README.md +83 -139
  2. package/dist/collections/Workflow.d.ts +3 -0
  3. package/dist/collections/Workflow.js +46 -2
  4. package/dist/collections/Workflow.js.map +1 -1
  5. package/dist/collections/WorkflowRuns.d.ts +2 -0
  6. package/dist/components/ErrorDisplay.d.ts +9 -0
  7. package/dist/components/ReadOnlyBanner.d.ts +2 -0
  8. package/dist/components/ReadOnlyBanner.js +67 -0
  9. package/dist/components/ReadOnlyBanner.js.map +1 -0
  10. package/dist/components/StatusCell.d.ts +6 -0
  11. package/dist/components/WorkflowBuilder/StepConfigurationForm.d.ts +34 -0
  12. package/dist/components/WorkflowBuilder/WorkflowBuilder.d.ts +40 -0
  13. package/dist/components/WorkflowBuilder/WorkflowToolbar.d.ts +14 -0
  14. package/dist/components/WorkflowBuilder/index.d.ts +4 -0
  15. package/dist/components/WorkflowBuilder/nodes/StepNode.d.ts +3 -0
  16. package/dist/core/trigger-custom-workflow.d.ts +52 -0
  17. package/dist/core/workflow-executor.d.ts +90 -0
  18. package/dist/exports/client.d.ts +3 -0
  19. package/dist/exports/client.js +2 -1
  20. package/dist/exports/client.js.map +1 -1
  21. package/dist/exports/fields.d.ts +1 -0
  22. package/dist/exports/rsc.d.ts +1 -0
  23. package/dist/exports/server.d.ts +5 -0
  24. package/dist/exports/views.d.ts +1 -0
  25. package/dist/fields/WorkflowBuilderField.d.ts +7 -0
  26. package/dist/fields/parameter.d.ts +4 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/plugin/collection-hook.d.ts +1 -0
  30. package/dist/plugin/config-types.d.ts +36 -0
  31. package/dist/plugin/config-types.js.map +1 -1
  32. package/dist/plugin/global-hook.d.ts +1 -0
  33. package/dist/plugin/index.d.ts +4 -0
  34. package/dist/plugin/index.js +53 -0
  35. package/dist/plugin/index.js.map +1 -1
  36. package/dist/plugin/logger.d.ts +20 -0
  37. package/dist/steps/create-document-handler.d.ts +2 -0
  38. package/dist/steps/create-document.d.ts +46 -0
  39. package/dist/steps/delete-document-handler.d.ts +2 -0
  40. package/dist/steps/delete-document.d.ts +39 -0
  41. package/dist/steps/http-request-handler.d.ts +2 -0
  42. package/dist/steps/http-request.d.ts +155 -0
  43. package/dist/steps/index.d.ts +12 -0
  44. package/dist/steps/read-document-handler.d.ts +2 -0
  45. package/dist/steps/read-document.d.ts +46 -0
  46. package/dist/steps/send-email-handler.d.ts +2 -0
  47. package/dist/steps/send-email.d.ts +44 -0
  48. package/dist/steps/update-document-handler.d.ts +2 -0
  49. package/dist/steps/update-document.d.ts +46 -0
  50. package/dist/triggers/collection-trigger.d.ts +2 -0
  51. package/dist/triggers/global-trigger.d.ts +2 -0
  52. package/dist/triggers/index.d.ts +2 -0
  53. package/dist/triggers/types.d.ts +5 -0
  54. package/dist/types/index.d.ts +24 -0
  55. package/dist/types/index.js +1 -0
  56. package/dist/types/index.js.map +1 -1
  57. package/package.json +4 -3
package/README.md CHANGED
@@ -1,18 +1,19 @@
1
1
  # @xtr-dev/payload-automation
2
2
 
3
- A comprehensive workflow automation plugin for PayloadCMS 3.x that enables visual workflow building, execution tracking, and parallel processing.
3
+ [![npm version](https://badge.fury.io/js/@xtr-dev%2Fpayload-automation.svg)](https://www.npmjs.com/package/@xtr-dev/payload-automation)
4
+
5
+ A workflow automation plugin for PayloadCMS 3.x. Run steps in workflows triggered by document changes or webhooks.
4
6
 
5
7
  ⚠️ **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
8
 
7
9
  ## Features
8
10
 
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
- - **Scheduled Workflows** - Use webhook triggers with external cron services
13
- - 📊 **Execution Tracking** - Complete history and monitoring of workflow runs
14
- - 🔧 **Extensible Steps** - HTTP requests, document CRUD, email notifications
15
- - 🔍 **JSONPath Integration** - Dynamic data interpolation and transformation
11
+ - 🔄 Visual workflow builder in PayloadCMS admin
12
+ - ⚡ Run workflows when documents are created/updated/deleted
13
+ - 🎯 Trigger workflows via webhooks
14
+ - 📊 Track workflow execution history
15
+ - 🔧 HTTP requests, document operations, email sending
16
+ - 🔗 Use data from previous steps in templates
16
17
 
17
18
  ## Installation
18
19
 
@@ -47,94 +48,76 @@ export default buildConfig({
47
48
  })
48
49
  ```
49
50
 
50
- ## Import Structure
51
-
52
- The plugin uses separate exports to avoid bundling server-side code in client bundles:
51
+ ## Imports
53
52
 
54
53
  ```typescript
55
- // Server-side plugin and functions
54
+ // Server plugin
56
55
  import { workflowsPlugin } from '@xtr-dev/payload-automation/server'
57
56
 
58
- // Client-side components
57
+ // Client components
59
58
  import { StatusCell, ErrorDisplay } from '@xtr-dev/payload-automation/client'
60
59
 
61
- // Helper utilities
62
- import { /* helpers */ } from '@xtr-dev/payload-automation/helpers'
63
-
64
- // Types only (safe for both server and client)
65
- import type { WorkflowsPluginConfig } from '@xtr-dev/payload-automation'
60
+ // Types
61
+ import type { WorkflowsPluginConfig, SeedWorkflow } from '@xtr-dev/payload-automation'
66
62
  ```
67
63
 
68
- ## Step Types
69
-
70
- ### HTTP Request
71
- Make external API calls with comprehensive error handling and retry logic.
72
-
73
- **Key Features:**
74
- - Support for GET, POST, PUT, DELETE, PATCH methods
75
- - Authentication: Bearer token, Basic auth, API key headers
76
- - Configurable timeouts and retry logic
77
- - JSONPath integration for dynamic URLs and request bodies
78
-
79
- **Error Handling:**
80
- HTTP Request steps use a **response-based success model** rather than status-code-based failures:
64
+ ## Seeding Template Workflows
81
65
 
82
- - **Successful completion**: All HTTP requests that receive a response (including 4xx/5xx status codes) are marked as "succeeded"
83
- - ❌ **Failed execution**: Only network errors, timeouts, DNS failures, and connection issues cause step failure
84
- - 📊 **Error information preserved**: HTTP error status codes (404, 500, etc.) are captured in the step output for workflow conditional logic
66
+ Provide read-only example workflows for users to learn from and reference:
85
67
 
86
- **Example workflow logic:**
87
68
  ```typescript
88
- // Step outputs for a 404 response:
89
- {
90
- "status": 404,
91
- "statusText": "Not Found",
92
- "body": "Resource not found",
93
- "headers": {...},
94
- "duration": 1200
95
- }
69
+ import type { SeedWorkflow } from '@xtr-dev/payload-automation'
70
+
71
+ const exampleWorkflows: SeedWorkflow[] = [
72
+ {
73
+ slug: 'example-welcome-email',
74
+ name: 'Example: Send Welcome Email',
75
+ description: 'Send email when user is created',
76
+ triggers: [
77
+ {
78
+ type: 'collection',
79
+ parameters: {
80
+ collection: 'users',
81
+ hook: 'afterCreate',
82
+ },
83
+ },
84
+ ],
85
+ steps: [
86
+ {
87
+ name: 'Send Email',
88
+ type: 'send-email',
89
+ input: {
90
+ to: '$.trigger.doc.email',
91
+ subject: 'Welcome!',
92
+ text: 'Thanks for joining us!',
93
+ },
94
+ },
95
+ ],
96
+ },
97
+ ]
96
98
 
97
- // Use in workflow conditions:
98
- // "$.steps.apiRequest.output.status >= 400" to handle errors
99
+ workflowsPlugin({
100
+ seedWorkflows: exampleWorkflows,
101
+ // ... other config
102
+ })
99
103
  ```
100
104
 
101
- This design allows workflows to handle HTTP errors gracefully rather than failing completely, enabling robust error handling and retry logic.
105
+ Seeded workflows:
106
+ - Are automatically created on first startup
107
+ - Use slug as unique identifier (stable across renames)
108
+ - Automatically update when definition changes in code
109
+ - Cannot be edited or deleted via UI or API
110
+ - Show a warning banner in the admin panel
111
+ - Can be duplicated to create editable versions
102
112
 
103
- **Enhanced Error Tracking:**
104
- For network failures (timeouts, DNS errors, connection failures), the plugin provides detailed error information through an independent storage system that bypasses PayloadCMS's output limitations:
113
+ See [docs/SEEDING_WORKFLOWS.md](./docs/SEEDING_WORKFLOWS.md) for detailed documentation.
105
114
 
106
- ```typescript
107
- // Timeout error details preserved in workflow context:
108
- {
109
- "steps": {
110
- "httpStep": {
111
- "state": "failed",
112
- "error": "Task handler returned a failed state",
113
- "errorDetails": {
114
- "errorType": "timeout",
115
- "duration": 2006,
116
- "attempts": 1,
117
- "finalError": "Request timeout after 2000ms",
118
- "context": {
119
- "url": "https://api.example.com/data",
120
- "method": "GET",
121
- "timeout": 2000
122
- }
123
- },
124
- "executionInfo": {
125
- "completed": true,
126
- "success": false,
127
- "executedAt": "2025-09-04T15:16:10.000Z",
128
- "duration": 2006
129
- }
130
- }
131
- }
132
- }
115
+ ## Step Types
133
116
 
134
- // Access in workflow conditions:
135
- // "$.steps.httpStep.errorDetails.errorType == 'timeout'"
136
- // "$.steps.httpStep.errorDetails.duration > 5000"
137
- ```
117
+ ### HTTP Request
118
+ Call external APIs. Supports GET, POST, PUT, DELETE, PATCH. Uses Bearer tokens, API keys, or basic auth.
119
+
120
+ HTTP steps succeed even with 4xx/5xx status codes. Only network errors (timeouts, DNS failures) cause step failure. Check `{{steps.stepName.output.status}}` for error handling.
138
121
 
139
122
  ### Document Operations
140
123
  - **Create Document** - Create PayloadCMS documents
@@ -145,13 +128,20 @@ For network failures (timeouts, DNS errors, connection failures), the plugin pro
145
128
  ### Communication
146
129
  - **Send Email** - Send notifications via PayloadCMS email
147
130
 
148
- ## Data Resolution
131
+ ## Templates
149
132
 
150
- Use JSONPath to access workflow data:
133
+ Use `{{}}` to insert data:
151
134
 
152
- - `$.trigger.doc.id` - Access trigger document
153
- - `$.steps.stepName.output` - Use previous step outputs
154
- - `$.context` - Access workflow context
135
+ - `{{trigger.doc.id}}` - Data from the document that triggered the workflow
136
+ - `{{steps.stepName.output}}` - Data from previous steps
137
+
138
+ Example:
139
+ ```json
140
+ {
141
+ "url": "https://api.example.com/posts/{{steps.createPost.output.id}}",
142
+ "condition": "{{trigger.doc.status}} == 'published'"
143
+ }
144
+ ```
155
145
 
156
146
  ## Requirements
157
147
 
@@ -159,72 +149,26 @@ Use JSONPath to access workflow data:
159
149
  - Node.js ^18.20.2 || >=20.9.0
160
150
  - pnpm ^9 || ^10
161
151
 
162
- ## Environment Variables
163
-
164
- Control plugin logging with these environment variables:
165
-
166
- ### `PAYLOAD_AUTOMATION_LOG_LEVEL`
167
- Controls both configuration-time and runtime logging.
168
- - **Values**: `silent`, `error`, `warn`, `info`, `debug`, `trace`
169
- - **Default**: `warn`
170
- - **Example**: `PAYLOAD_AUTOMATION_LOG_LEVEL=debug`
152
+ ## Logging
171
153
 
172
- ### `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL` (optional)
173
- Override log level specifically for configuration-time logs (plugin setup).
174
- - **Values**: Same as above
175
- - **Default**: Falls back to `PAYLOAD_AUTOMATION_LOG_LEVEL` or `warn`
176
- - **Example**: `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL=silent`
154
+ Set `PAYLOAD_AUTOMATION_LOG_LEVEL` to control logs:
155
+ - `silent`, `error`, `warn` (default), `info`, `debug`, `trace`
177
156
 
178
- ### Production Usage
179
- For production, keep the default (`warn`) or use `error` or `silent`:
180
- ```bash
181
- PAYLOAD_AUTOMATION_LOG_LEVEL=error npm start
182
- ```
183
-
184
- ### Development Usage
185
- For debugging, use `debug` or `info`:
186
157
  ```bash
187
158
  PAYLOAD_AUTOMATION_LOG_LEVEL=debug npm run dev
188
159
  ```
189
160
 
190
161
  ## Scheduled Workflows
191
162
 
192
- For scheduled workflows, use **webhook triggers** with external cron services instead of built-in cron triggers:
193
-
194
- ### GitHub Actions (Free)
195
- ```yaml
196
- # .github/workflows/daily-report.yml
197
- on:
198
- schedule:
199
- - cron: '0 9 * * *' # Daily at 9 AM UTC
200
- jobs:
201
- trigger-workflow:
202
- runs-on: ubuntu-latest
203
- steps:
204
- - run: curl -X POST https://your-app.com/api/workflows-webhook/daily-report
205
- ```
163
+ Use webhook triggers with external cron services:
206
164
 
207
- ### Vercel Cron (Serverless)
208
- ```js
209
- // api/cron/daily.js
210
- export default async function handler(req, res) {
211
- await fetch('https://your-app.com/api/workflows-webhook/daily-report', {
212
- method: 'POST',
213
- headers: { 'Content-Type': 'application/json' },
214
- body: JSON.stringify({ source: 'vercel-cron' })
215
- });
216
- res.status(200).json({ success: true });
217
- }
165
+ ```bash
166
+ # Call workflow webhook from cron
167
+ curl -X POST https://your-app.com/api/workflows-webhook/daily-report
218
168
  ```
219
169
 
220
- **Benefits**: Better reliability, proper process isolation, easier debugging, and leverages existing infrastructure.
221
-
222
- **Note**: Built-in cron triggers have been removed in v0.0.37+ to focus on webhook-based scheduling which provides better reliability and debugging capabilities.
223
-
224
- ## Documentation
225
-
226
- Full documentation coming soon. For now, explore the development environment in the repository for examples and patterns.
170
+ Built-in cron triggers were removed in v0.0.37+.
227
171
 
228
172
  ## License
229
173
 
230
- MIT
174
+ 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;
@@ -7,13 +7,27 @@ export const createWorkflowCollection = (options)=>{
7
7
  slug: 'workflows',
8
8
  access: {
9
9
  create: ()=>true,
10
- delete: ()=>true,
10
+ delete: ({ req, data })=>{
11
+ // Prevent deletion of read-only workflows
12
+ if (data?.readOnly === true) {
13
+ return false;
14
+ }
15
+ return true;
16
+ },
11
17
  read: ()=>true,
12
- update: ()=>true
18
+ update: ({ req, data })=>{
19
+ // Prevent updates to read-only workflows
20
+ if (data?.readOnly === true) {
21
+ return false;
22
+ }
23
+ return true;
24
+ }
13
25
  },
14
26
  admin: {
15
27
  defaultColumns: [
16
28
  'name',
29
+ 'slug',
30
+ 'readOnly',
17
31
  'updatedAt'
18
32
  ],
19
33
  description: 'Create and manage automated workflows.',
@@ -29,6 +43,36 @@ export const createWorkflowCollection = (options)=>{
29
43
  },
30
44
  required: true
31
45
  },
46
+ {
47
+ name: 'slug',
48
+ type: 'text',
49
+ admin: {
50
+ description: 'URL-safe unique identifier for this workflow',
51
+ position: 'sidebar'
52
+ },
53
+ index: true,
54
+ unique: true
55
+ },
56
+ {
57
+ name: 'readOnly',
58
+ type: 'checkbox',
59
+ admin: {
60
+ description: 'Read-only workflows cannot be edited or deleted. This is typically used for seeded template workflows.',
61
+ position: 'sidebar',
62
+ readOnly: true
63
+ },
64
+ defaultValue: false
65
+ },
66
+ {
67
+ name: 'readOnlyBanner',
68
+ type: 'ui',
69
+ admin: {
70
+ components: {
71
+ Field: '@xtr-dev/payload-automation/client#ReadOnlyBanner'
72
+ },
73
+ condition: (data)=>data?.readOnly === true
74
+ }
75
+ },
32
76
  {
33
77
  name: 'description',
34
78
  type: 'textarea',
@@ -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: () => 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 ...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","read","update","admin","defaultColumns","description","group","useAsTitle","fields","name","type","required","hidden","defaultValue","flatMap","parameters","p","hasMany","versions","drafts","autosave","maxPerDoc"],"mappings":"AAIA,SAAQA,SAAS,QAAO,yBAAwB;AAChD,SAAQC,iBAAiB,EAAEC,aAAa,QAAO,uBAAsB;AAErE,OAAO,MAAMC,2BAAsG,CAACC;IAClH,MAAMC,QAAQD,QAAQC,KAAK,IAAI,EAAE;IACjC,MAAMC,WAAW,AAACF,CAAAA,QAAQE,QAAQ,IAAI,EAAE,AAAD,EAAGC,GAAG,CAACC,CAAAA,IAAKA,EAAEJ,UAAUK,MAAM,CAACR,kBAAkBG,UAAUF,cAAcE;IAChH,OAAO;QACLM,MAAM;QACNC,QAAQ;YACNC,QAAQ,IAAM;YACdC,QAAQ,IAAM;YACdC,MAAM,IAAM;YACZC,QAAQ,IAAM;QAChB;QACAC,OAAO;YACLC,gBAAgB;gBAAC;gBAAQ;aAAY;YACrCC,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;gBACNF,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNnB,SAAS;+BACJE,SAASC,GAAG,CAACC,CAAAA,IAAKA,EAAEE,IAAI;yBAC5B;oBACH;oBACA;wBACEY,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLS,QAAQ;wBACV;wBACAC,cAAc,CAAC;oBACjB;oBACA,qCAAqC;uBAClCpB,SAASqB,OAAO,CAACnB,CAAAA,IAAK,AAACA,CAAAA,EAAEoB,UAAU,IAAI,EAAE,AAAD,EAAGrB,GAAG,CAACsB,CAAAA,IAAK7B,UAAUQ,EAAEE,IAAI,EAAEmB;oBACzE;wBACEP,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAM,UAAU;oBACZ;iBACD;YACH;YACA;gBACEF,MAAM;gBACNC,MAAM;gBACNF,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNG,cAAc;oBAChB;oBACA;wBACEJ,MAAM;wBACNC,MAAM;wBACNnB,SAASC,MAAME,GAAG,CAACC,CAAAA,IAAKA,EAAEE,IAAI;oBAChC;oBACA;wBACEY,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAQ,cAAc,CAAC;oBACjB;oBACA;wBACEJ,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAY,SAAS;wBACTN,UAAU;oBACZ;oBACA;wBACEF,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAM,UAAU;oBACZ;iBACD;YACH;SACD;QACDO,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\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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"}
@@ -0,0 +1,2 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ export declare const WorkflowRunsCollection: CollectionConfig;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface ErrorDisplayProps {
3
+ value?: string;
4
+ onChange?: (value: string) => void;
5
+ readOnly?: boolean;
6
+ path?: string;
7
+ }
8
+ export declare const ErrorDisplay: React.FC<ErrorDisplayProps>;
9
+ export {};
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const ReadOnlyBanner: React.FC;
@@ -0,0 +1,67 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import React from 'react';
4
+ export const ReadOnlyBanner = ()=>{
5
+ return /*#__PURE__*/ _jsxs("div", {
6
+ style: {
7
+ backgroundColor: '#fef3c7',
8
+ border: '1px solid #f59e0b',
9
+ borderRadius: '4px',
10
+ padding: '12px 16px',
11
+ marginBottom: '16px',
12
+ display: 'flex',
13
+ alignItems: 'center',
14
+ gap: '8px'
15
+ },
16
+ children: [
17
+ /*#__PURE__*/ _jsxs("svg", {
18
+ xmlns: "http://www.w3.org/2000/svg",
19
+ width: "20",
20
+ height: "20",
21
+ viewBox: "0 0 24 24",
22
+ fill: "none",
23
+ stroke: "#f59e0b",
24
+ strokeWidth: "2",
25
+ strokeLinecap: "round",
26
+ strokeLinejoin: "round",
27
+ children: [
28
+ /*#__PURE__*/ _jsx("path", {
29
+ d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
30
+ }),
31
+ /*#__PURE__*/ _jsx("line", {
32
+ x1: "12",
33
+ y1: "9",
34
+ x2: "12",
35
+ y2: "13"
36
+ }),
37
+ /*#__PURE__*/ _jsx("line", {
38
+ x1: "12",
39
+ y1: "17",
40
+ x2: "12.01",
41
+ y2: "17"
42
+ })
43
+ ]
44
+ }),
45
+ /*#__PURE__*/ _jsxs("div", {
46
+ children: [
47
+ /*#__PURE__*/ _jsx("strong", {
48
+ style: {
49
+ color: '#92400e'
50
+ },
51
+ children: "Read-Only Workflow"
52
+ }),
53
+ /*#__PURE__*/ _jsx("p", {
54
+ style: {
55
+ margin: '4px 0 0 0',
56
+ color: '#78350f',
57
+ fontSize: '14px'
58
+ },
59
+ children: "This is a template workflow that cannot be edited or deleted. You can view it for reference or duplicate it to create your own version."
60
+ })
61
+ ]
62
+ })
63
+ ]
64
+ });
65
+ };
66
+
67
+ //# sourceMappingURL=ReadOnlyBanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/ReadOnlyBanner.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nexport const ReadOnlyBanner: React.FC = () => {\n return (\n <div\n style={{\n backgroundColor: '#fef3c7',\n border: '1px solid #f59e0b',\n borderRadius: '4px',\n padding: '12px 16px',\n marginBottom: '16px',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#f59e0b\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" />\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" />\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n <div>\n <strong style={{ color: '#92400e' }}>Read-Only Workflow</strong>\n <p style={{ margin: '4px 0 0 0', color: '#78350f', fontSize: '14px' }}>\n This is a template workflow that cannot be edited or deleted. You can view it for reference or duplicate it to create your own version.\n </p>\n </div>\n </div>\n )\n}\n"],"names":["React","ReadOnlyBanner","div","style","backgroundColor","border","borderRadius","padding","marginBottom","display","alignItems","gap","svg","xmlns","width","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","path","d","line","x1","y1","x2","y2","strong","color","p","margin","fontSize"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,OAAO,MAAMC,iBAA2B;IACtC,qBACE,MAACC;QACCC,OAAO;YACLC,iBAAiB;YACjBC,QAAQ;YACRC,cAAc;YACdC,SAAS;YACTC,cAAc;YACdC,SAAS;YACTC,YAAY;YACZC,KAAK;QACP;;0BAEA,MAACC;gBACCC,OAAM;gBACNC,OAAM;gBACNC,QAAO;gBACPC,SAAQ;gBACRC,MAAK;gBACLC,QAAO;gBACPC,aAAY;gBACZC,eAAc;gBACdC,gBAAe;;kCAEf,KAACC;wBAAKC,GAAE;;kCACR,KAACC;wBAAKC,IAAG;wBAAKC,IAAG;wBAAIC,IAAG;wBAAKC,IAAG;;kCAChC,KAACJ;wBAAKC,IAAG;wBAAKC,IAAG;wBAAKC,IAAG;wBAAQC,IAAG;;;;0BAEtC,MAAC1B;;kCACC,KAAC2B;wBAAO1B,OAAO;4BAAE2B,OAAO;wBAAU;kCAAG;;kCACrC,KAACC;wBAAE5B,OAAO;4BAAE6B,QAAQ;4BAAaF,OAAO;4BAAWG,UAAU;wBAAO;kCAAG;;;;;;AAM/E,EAAC"}
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface StatusCellProps {
3
+ cellData: string;
4
+ }
5
+ export declare const StatusCell: React.FC<StatusCellProps>;
6
+ export {};
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import type { Node } from '@xyflow/react';
3
+ interface StepField {
4
+ name: string;
5
+ type: string;
6
+ label?: string;
7
+ admin?: {
8
+ description?: string;
9
+ condition?: (data: any, siblingData: any) => boolean;
10
+ };
11
+ options?: Array<{
12
+ label: string;
13
+ value: string;
14
+ }>;
15
+ defaultValue?: any;
16
+ required?: boolean;
17
+ hasMany?: boolean;
18
+ fields?: StepField[];
19
+ }
20
+ interface StepType {
21
+ slug: string;
22
+ label?: string;
23
+ inputSchema?: StepField[];
24
+ outputSchema?: StepField[];
25
+ }
26
+ interface StepConfigurationFormProps {
27
+ selectedNode: Node | null;
28
+ availableStepTypes: StepType[];
29
+ availableSteps: string[];
30
+ onNodeUpdate: (nodeId: string, data: Partial<Node['data']>) => void;
31
+ onClose: () => void;
32
+ }
33
+ export declare const StepConfigurationForm: React.FC<StepConfigurationFormProps>;
34
+ export {};
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import '@xyflow/react/dist/style.css';
3
+ interface WorkflowData {
4
+ id: string;
5
+ name: string;
6
+ steps?: Array<{
7
+ name: string;
8
+ type: string;
9
+ position?: {
10
+ x: number;
11
+ y: number;
12
+ };
13
+ visual?: {
14
+ color?: string;
15
+ icon?: string;
16
+ };
17
+ dependencies?: string[];
18
+ }>;
19
+ layout?: {
20
+ viewport?: {
21
+ x: number;
22
+ y: number;
23
+ zoom: number;
24
+ };
25
+ };
26
+ }
27
+ interface StepType {
28
+ slug: string;
29
+ label?: string;
30
+ inputSchema?: any[];
31
+ outputSchema?: any[];
32
+ }
33
+ interface WorkflowBuilderProps {
34
+ workflow?: WorkflowData;
35
+ availableStepTypes?: StepType[];
36
+ onSave?: (workflow: WorkflowData) => void;
37
+ readonly?: boolean;
38
+ }
39
+ export declare const WorkflowBuilder: React.FC<WorkflowBuilderProps>;
40
+ export {};
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ interface AvailableStepType {
3
+ slug: string;
4
+ label?: string;
5
+ inputSchema?: any[];
6
+ outputSchema?: any[];
7
+ }
8
+ interface WorkflowToolbarProps {
9
+ availableStepTypes: AvailableStepType[];
10
+ onAddStep: (stepType: string) => void;
11
+ onSave: () => void;
12
+ }
13
+ export declare const WorkflowToolbar: React.FC<WorkflowToolbarProps>;
14
+ export {};
@@ -0,0 +1,4 @@
1
+ export { WorkflowBuilder } from './WorkflowBuilder.js';
2
+ export { WorkflowToolbar } from './WorkflowToolbar.js';
3
+ export { StepConfigurationForm } from './StepConfigurationForm.js';
4
+ export { StepNode } from './nodes/StepNode.js';
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { NodeProps } from '@xyflow/react';
3
+ export declare const StepNode: React.FC<NodeProps>;
@@ -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>;