@xtr-dev/payload-automation 0.0.40 → 0.0.43

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 (59) hide show
  1. package/README.md +76 -160
  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/fields/parameter.js +8 -3
  28. package/dist/fields/parameter.js.map +1 -1
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/plugin/collection-hook.d.ts +1 -0
  32. package/dist/plugin/config-types.d.ts +36 -0
  33. package/dist/plugin/config-types.js.map +1 -1
  34. package/dist/plugin/global-hook.d.ts +1 -0
  35. package/dist/plugin/index.d.ts +4 -0
  36. package/dist/plugin/index.js +53 -0
  37. package/dist/plugin/index.js.map +1 -1
  38. package/dist/plugin/logger.d.ts +20 -0
  39. package/dist/steps/create-document-handler.d.ts +2 -0
  40. package/dist/steps/create-document.d.ts +46 -0
  41. package/dist/steps/delete-document-handler.d.ts +2 -0
  42. package/dist/steps/delete-document.d.ts +39 -0
  43. package/dist/steps/http-request-handler.d.ts +2 -0
  44. package/dist/steps/http-request.d.ts +155 -0
  45. package/dist/steps/index.d.ts +12 -0
  46. package/dist/steps/read-document-handler.d.ts +2 -0
  47. package/dist/steps/read-document.d.ts +46 -0
  48. package/dist/steps/send-email-handler.d.ts +2 -0
  49. package/dist/steps/send-email.d.ts +44 -0
  50. package/dist/steps/update-document-handler.d.ts +2 -0
  51. package/dist/steps/update-document.d.ts +46 -0
  52. package/dist/triggers/collection-trigger.d.ts +2 -0
  53. package/dist/triggers/global-trigger.d.ts +2 -0
  54. package/dist/triggers/index.d.ts +2 -0
  55. package/dist/triggers/types.d.ts +5 -0
  56. package/dist/types/index.d.ts +24 -0
  57. package/dist/types/index.js +1 -0
  58. package/dist/types/index.js.map +1 -1
  59. 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
- - 🔧 **Handlebars Templates** - Dynamic data interpolation with automatic type conversion
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.
64
+ ## Seeding Template Workflows
72
65
 
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
- - Handlebars templates for dynamic URLs and request bodies
66
+ Provide read-only example workflows for users to learn from and reference:
78
67
 
79
- **Error Handling:**
80
- HTTP Request steps use a **response-based success model** rather than status-code-based failures:
81
-
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
85
-
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,38 +128,17 @@ 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 Handlebars templates 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
155
-
156
- ### Template Examples
135
+ - `{{trigger.doc.id}}` - Data from the document that triggered the workflow
136
+ - `{{steps.stepName.output}}` - Data from previous steps
157
137
 
138
+ Example:
158
139
  ```json
159
140
  {
160
141
  "url": "https://api.example.com/posts/{{steps.createPost.output.id}}",
161
- "message": "Post {{trigger.doc.title}} was updated by {{trigger.req.user.email}}",
162
- "timeout": "{{steps.configStep.output.timeoutMs}}"
163
- }
164
- ```
165
-
166
- ### Automatic Type Conversion
167
-
168
- Handlebars templates automatically convert string results to appropriate types based on field names:
169
-
170
- - **Numbers**: `timeout`, `retries`, `delay`, `port`, `count`, etc. → converted to numbers
171
- - **Booleans**: `enabled`, `active`, `success`, `complete`, etc. → converted to booleans
172
- - **Numeric strings**: `"5000"` → `5000`, `"3.14"` → `3.14`
173
-
174
- ### Conditions
175
-
176
- Conditions support Handlebars templates with comparison operators:
177
-
178
- ```json
179
- {
180
142
  "condition": "{{trigger.doc.status}} == 'published'"
181
143
  }
182
144
  ```
@@ -187,72 +149,26 @@ Conditions support Handlebars templates with comparison operators:
187
149
  - Node.js ^18.20.2 || >=20.9.0
188
150
  - pnpm ^9 || ^10
189
151
 
190
- ## Environment Variables
152
+ ## Logging
191
153
 
192
- Control plugin logging with these environment variables:
154
+ Set `PAYLOAD_AUTOMATION_LOG_LEVEL` to control logs:
155
+ - `silent`, `error`, `warn` (default), `info`, `debug`, `trace`
193
156
 
194
- ### `PAYLOAD_AUTOMATION_LOG_LEVEL`
195
- Controls both configuration-time and runtime logging.
196
- - **Values**: `silent`, `error`, `warn`, `info`, `debug`, `trace`
197
- - **Default**: `warn`
198
- - **Example**: `PAYLOAD_AUTOMATION_LOG_LEVEL=debug`
199
-
200
- ### `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL` (optional)
201
- Override log level specifically for configuration-time logs (plugin setup).
202
- - **Values**: Same as above
203
- - **Default**: Falls back to `PAYLOAD_AUTOMATION_LOG_LEVEL` or `warn`
204
- - **Example**: `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL=silent`
205
-
206
- ### Production Usage
207
- For production, keep the default (`warn`) or use `error` or `silent`:
208
- ```bash
209
- PAYLOAD_AUTOMATION_LOG_LEVEL=error npm start
210
- ```
211
-
212
- ### Development Usage
213
- For debugging, use `debug` or `info`:
214
157
  ```bash
215
158
  PAYLOAD_AUTOMATION_LOG_LEVEL=debug npm run dev
216
159
  ```
217
160
 
218
161
  ## Scheduled Workflows
219
162
 
220
- For scheduled workflows, use **webhook triggers** with external cron services instead of built-in cron triggers:
221
-
222
- ### GitHub Actions (Free)
223
- ```yaml
224
- # .github/workflows/daily-report.yml
225
- on:
226
- schedule:
227
- - cron: '0 9 * * *' # Daily at 9 AM UTC
228
- jobs:
229
- trigger-workflow:
230
- runs-on: ubuntu-latest
231
- steps:
232
- - run: curl -X POST https://your-app.com/api/workflows-webhook/daily-report
233
- ```
163
+ Use webhook triggers with external cron services:
234
164
 
235
- ### Vercel Cron (Serverless)
236
- ```js
237
- // api/cron/daily.js
238
- export default async function handler(req, res) {
239
- await fetch('https://your-app.com/api/workflows-webhook/daily-report', {
240
- method: 'POST',
241
- headers: { 'Content-Type': 'application/json' },
242
- body: JSON.stringify({ source: 'vercel-cron' })
243
- });
244
- res.status(200).json({ success: true });
245
- }
165
+ ```bash
166
+ # Call workflow webhook from cron
167
+ curl -X POST https://your-app.com/api/workflows-webhook/daily-report
246
168
  ```
247
169
 
248
- **Benefits**: Better reliability, proper process isolation, easier debugging, and leverages existing infrastructure.
249
-
250
- **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.
251
-
252
- ## Documentation
253
-
254
- 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+.
255
171
 
256
172
  ## License
257
173
 
258
- 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>;