@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.
- package/README.md +76 -160
- package/dist/collections/Workflow.d.ts +3 -0
- package/dist/collections/Workflow.js +46 -2
- package/dist/collections/Workflow.js.map +1 -1
- package/dist/collections/WorkflowRuns.d.ts +2 -0
- package/dist/components/ErrorDisplay.d.ts +9 -0
- package/dist/components/ReadOnlyBanner.d.ts +2 -0
- package/dist/components/ReadOnlyBanner.js +67 -0
- package/dist/components/ReadOnlyBanner.js.map +1 -0
- package/dist/components/StatusCell.d.ts +6 -0
- package/dist/components/WorkflowBuilder/StepConfigurationForm.d.ts +34 -0
- package/dist/components/WorkflowBuilder/WorkflowBuilder.d.ts +40 -0
- package/dist/components/WorkflowBuilder/WorkflowToolbar.d.ts +14 -0
- package/dist/components/WorkflowBuilder/index.d.ts +4 -0
- package/dist/components/WorkflowBuilder/nodes/StepNode.d.ts +3 -0
- package/dist/core/trigger-custom-workflow.d.ts +52 -0
- package/dist/core/workflow-executor.d.ts +90 -0
- package/dist/exports/client.d.ts +3 -0
- package/dist/exports/client.js +2 -1
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/fields.d.ts +1 -0
- package/dist/exports/rsc.d.ts +1 -0
- package/dist/exports/server.d.ts +5 -0
- package/dist/exports/views.d.ts +1 -0
- package/dist/fields/WorkflowBuilderField.d.ts +7 -0
- package/dist/fields/parameter.d.ts +4 -0
- package/dist/fields/parameter.js +8 -3
- package/dist/fields/parameter.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js.map +1 -1
- package/dist/plugin/collection-hook.d.ts +1 -0
- package/dist/plugin/config-types.d.ts +36 -0
- package/dist/plugin/config-types.js.map +1 -1
- package/dist/plugin/global-hook.d.ts +1 -0
- package/dist/plugin/index.d.ts +4 -0
- package/dist/plugin/index.js +53 -0
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/logger.d.ts +20 -0
- package/dist/steps/create-document-handler.d.ts +2 -0
- package/dist/steps/create-document.d.ts +46 -0
- package/dist/steps/delete-document-handler.d.ts +2 -0
- package/dist/steps/delete-document.d.ts +39 -0
- package/dist/steps/http-request-handler.d.ts +2 -0
- package/dist/steps/http-request.d.ts +155 -0
- package/dist/steps/index.d.ts +12 -0
- package/dist/steps/read-document-handler.d.ts +2 -0
- package/dist/steps/read-document.d.ts +46 -0
- package/dist/steps/send-email-handler.d.ts +2 -0
- package/dist/steps/send-email.d.ts +44 -0
- package/dist/steps/update-document-handler.d.ts +2 -0
- package/dist/steps/update-document.d.ts +46 -0
- package/dist/triggers/collection-trigger.d.ts +2 -0
- package/dist/triggers/global-trigger.d.ts +2 -0
- package/dist/triggers/index.d.ts +2 -0
- package/dist/triggers/types.d.ts +5 -0
- package/dist/types/index.d.ts +24 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# @xtr-dev/payload-automation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](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
|
-
- 🔄
|
|
10
|
-
- ⚡
|
|
11
|
-
- 🎯
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
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
|
-
##
|
|
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
|
|
54
|
+
// Server plugin
|
|
56
55
|
import { workflowsPlugin } from '@xtr-dev/payload-automation/server'
|
|
57
56
|
|
|
58
|
-
// Client
|
|
57
|
+
// Client components
|
|
59
58
|
import { StatusCell, ErrorDisplay } from '@xtr-dev/payload-automation/client'
|
|
60
59
|
|
|
61
|
-
//
|
|
62
|
-
import {
|
|
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
|
-
##
|
|
69
|
-
|
|
70
|
-
### HTTP Request
|
|
71
|
-
Make external API calls with comprehensive error handling and retry logic.
|
|
64
|
+
## Seeding Template Workflows
|
|
72
65
|
|
|
73
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
+
workflowsPlugin({
|
|
100
|
+
seedWorkflows: exampleWorkflows,
|
|
101
|
+
// ... other config
|
|
102
|
+
})
|
|
99
103
|
```
|
|
100
104
|
|
|
101
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
##
|
|
131
|
+
## Templates
|
|
149
132
|
|
|
150
|
-
Use
|
|
133
|
+
Use `{{}}` to insert data:
|
|
151
134
|
|
|
152
|
-
- `{{trigger.doc.id}}` -
|
|
153
|
-
- `{{steps.stepName.output}}` -
|
|
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
|
-
##
|
|
152
|
+
## Logging
|
|
191
153
|
|
|
192
|
-
|
|
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
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
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
|
|
@@ -7,13 +7,27 @@ export const createWorkflowCollection = (options)=>{
|
|
|
7
7
|
slug: 'workflows',
|
|
8
8
|
access: {
|
|
9
9
|
create: ()=>true,
|
|
10
|
-
delete: ()=>
|
|
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: ()=>
|
|
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","
|
|
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,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,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 {};
|