@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.
- package/README.md +83 -139
- 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/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
|
-
- 🔍 **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
|
-
##
|
|
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.
|
|
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
|
-
-
|
|
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
|
-
|
|
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,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
|
-
##
|
|
131
|
+
## Templates
|
|
149
132
|
|
|
150
|
-
Use
|
|
133
|
+
Use `{{}}` to insert data:
|
|
151
134
|
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
173
|
-
|
|
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
|
-
|
|
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
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
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
|
|
@@ -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":"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,CAAC,EAAEC,GAAG,EAAEC,IAAI,EAAE;gBACpB,0CAA0C;gBAC1C,IAAIA,MAAMC,aAAa,MAAM;oBAC3B,OAAO;gBACT;gBACA,OAAO;YACT;YACAC,MAAM,IAAM;YACZC,QAAQ,CAAC,EAAEJ,GAAG,EAAEC,IAAI,EAAE;gBACpB,yCAAyC;gBACzC,IAAIA,MAAMC,aAAa,MAAM;oBAC3B,OAAO;gBACT;gBACA,OAAO;YACT;QACF;QACAG,OAAO;YACLC,gBAAgB;gBAAC;gBAAQ;gBAAQ;gBAAY;aAAY;YACzDC,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;oBACbO,UAAU;gBACZ;gBACAC,OAAO;gBACPC,QAAQ;YACV;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;oBACbO,UAAU;oBACVZ,UAAU;gBACZ;gBACAe,cAAc;YAChB;YACA;gBACEN,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLa,YAAY;wBACVC,OAAO;oBACT;oBACAC,WAAW,CAACnB,OAASA,MAAMC,aAAa;gBAC1C;YACF;YACA;gBACES,MAAM;gBACNC,MAAM;gBACNP,OAAO;oBACLE,aAAa;gBACf;YACF;YACA;gBACEI,MAAM;gBACNC,MAAM;gBACNF,QAAQ;oBACN;wBACEC,MAAM;wBACNC,MAAM;wBACNtB,SAAS;+BACJE,SAASC,GAAG,CAACC,CAAAA,IAAKA,EAAEE,IAAI;yBAC5B;oBACH;oBACA;wBACEe,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLgB,QAAQ;wBACV;wBACAJ,cAAc,CAAC;oBACjB;oBACA,qCAAqC;uBAClCzB,SAAS8B,OAAO,CAAC5B,CAAAA,IAAK,AAACA,CAAAA,EAAE6B,UAAU,IAAI,EAAE,AAAD,EAAG9B,GAAG,CAAC+B,CAAAA,IAAKtC,UAAUQ,EAAEE,IAAI,EAAE4B;oBACzE;wBACEb,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;wBACNK,cAAc;oBAChB;oBACA;wBACEN,MAAM;wBACNC,MAAM;wBACNtB,SAASC,MAAME,GAAG,CAACC,CAAAA,IAAKA,EAAEE,IAAI;oBAChC;oBACA;wBACEe,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAU,cAAc,CAAC;oBACjB;oBACA;wBACEN,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAkB,SAAS;wBACTZ,UAAU;oBACZ;oBACA;wBACEF,MAAM;wBACNC,MAAM;wBACNP,OAAO;4BACLE,aAAa;wBACf;wBACAM,UAAU;oBACZ;iBACD;YACH;SACD;QACDa,UAAU;YACRC,QAAQ;gBACNC,UAAU;YACZ;YACAC,WAAW;QACb;IACF;AACF,EAAC"}
|
|
@@ -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 {};
|
|
@@ -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>;
|