@xtr-dev/payload-automation 0.0.43 → 0.0.46
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 +221 -49
- package/dist/collections/Steps.d.ts +6 -0
- package/dist/collections/Steps.js +166 -0
- package/dist/collections/Steps.js.map +1 -0
- package/dist/collections/Triggers.d.ts +7 -0
- package/dist/collections/Triggers.js +224 -0
- package/dist/collections/Triggers.js.map +1 -0
- package/dist/collections/Workflow.d.ts +5 -2
- package/dist/collections/Workflow.js +179 -39
- package/dist/collections/Workflow.js.map +1 -1
- package/dist/collections/WorkflowRuns.d.ts +4 -0
- package/dist/collections/WorkflowRuns.js +219 -24
- package/dist/collections/WorkflowRuns.js.map +1 -1
- package/dist/components/WorkflowBuilder/WorkflowBuilder.js.map +1 -1
- package/dist/core/expression-engine.d.ts +58 -0
- package/dist/core/expression-engine.js +191 -0
- package/dist/core/expression-engine.js.map +1 -0
- package/dist/core/workflow-executor.d.ts +70 -56
- package/dist/core/workflow-executor.js +354 -677
- package/dist/core/workflow-executor.js.map +1 -1
- package/dist/exports/client.js +1 -3
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/views.js +2 -4
- package/dist/exports/views.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin/config-types.d.ts +43 -5
- package/dist/plugin/config-types.js +3 -1
- package/dist/plugin/config-types.js.map +1 -1
- package/dist/plugin/index.d.ts +1 -1
- package/dist/plugin/index.js +150 -55
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/trigger-hook.d.ts +13 -0
- package/dist/plugin/trigger-hook.js +184 -0
- package/dist/plugin/trigger-hook.js.map +1 -0
- package/dist/steps/create-step.d.ts +66 -0
- package/dist/steps/create-step.js +59 -0
- package/dist/steps/create-step.js.map +1 -0
- package/dist/steps/index.d.ts +2 -0
- package/dist/steps/index.js +3 -0
- package/dist/steps/index.js.map +1 -1
- package/dist/steps/read-document-handler.js +1 -1
- package/dist/steps/read-document-handler.js.map +1 -1
- package/dist/steps/update-document-handler.js +1 -1
- package/dist/steps/update-document-handler.js.map +1 -1
- package/dist/triggers/hook-options.d.ts +34 -0
- package/dist/triggers/hook-options.js +158 -0
- package/dist/triggers/hook-options.js.map +1 -0
- package/dist/triggers/index.d.ts +2 -2
- package/dist/triggers/index.js +1 -2
- package/dist/triggers/index.js.map +1 -1
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.js +4 -5
- package/dist/types/index.js.map +1 -1
- package/dist/utils/validation.d.ts +64 -0
- package/dist/utils/validation.js +107 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +2 -1
- package/dist/plugin/collection-hook.d.ts +0 -1
- package/dist/plugin/collection-hook.js +0 -92
- package/dist/plugin/collection-hook.js.map +0 -1
- package/dist/plugin/global-hook.d.ts +0 -1
- package/dist/plugin/global-hook.js +0 -83
- package/dist/plugin/global-hook.js.map +0 -1
- package/dist/triggers/collection-trigger.d.ts +0 -2
- package/dist/triggers/collection-trigger.js +0 -36
- package/dist/triggers/collection-trigger.js.map +0 -1
- package/dist/triggers/global-trigger.d.ts +0 -2
- package/dist/triggers/global-trigger.js +0 -29
- package/dist/triggers/global-trigger.js.map +0 -1
- package/dist/triggers/types.d.ts +0 -5
- package/dist/triggers/types.js +0 -3
- package/dist/triggers/types.js.map +0 -1
package/dist/plugin/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import { createTriggersCollection } from '../collections/Triggers.js';
|
|
2
|
+
import { createStepsCollection } from '../collections/Steps.js';
|
|
1
3
|
import { createWorkflowCollection } from '../collections/Workflow.js';
|
|
2
4
|
import { WorkflowRunsCollection } from '../collections/WorkflowRuns.js';
|
|
3
5
|
import { getConfigLogger, initializeLogger } from './logger.js';
|
|
4
|
-
import { createCollectionTriggerHook } from
|
|
5
|
-
import { createGlobalTriggerHook } from "./global-hook.js";
|
|
6
|
+
import { createCollectionTriggerHook, createGlobalTriggerHook } from './trigger-hook.js';
|
|
6
7
|
export { getLogger } from './logger.js';
|
|
7
8
|
const applyCollectionsConfig = (pluginOptions, config)=>{
|
|
8
|
-
// Add workflow collections
|
|
9
9
|
if (!config.collections) {
|
|
10
10
|
config.collections = [];
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
// Add all automation collections
|
|
13
|
+
config.collections.push(createTriggersCollection(pluginOptions), createStepsCollection(pluginOptions.steps), createWorkflowCollection(), WorkflowRunsCollection);
|
|
13
14
|
};
|
|
14
15
|
export const workflowsPlugin = (pluginOptions)=>(config)=>{
|
|
15
16
|
// If the plugin is disabled, return config unchanged
|
|
@@ -17,44 +18,36 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
|
|
|
17
18
|
return config;
|
|
18
19
|
}
|
|
19
20
|
applyCollectionsConfig(pluginOptions, config);
|
|
20
|
-
// CRITICAL: Modify existing collection configs BEFORE PayloadCMS processes them
|
|
21
|
-
// This is the ONLY time we can add hooks that will actually work
|
|
22
21
|
const logger = getConfigLogger();
|
|
22
|
+
// Register collection hooks
|
|
23
23
|
if (config.collections && pluginOptions.collectionTriggers) {
|
|
24
24
|
for (const [collectionSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)){
|
|
25
25
|
if (!triggerConfig) {
|
|
26
26
|
continue;
|
|
27
27
|
}
|
|
28
|
-
// Find the collection config that matches
|
|
29
28
|
const collectionIndex = config.collections.findIndex((c)=>c.slug === collectionSlug);
|
|
30
29
|
if (collectionIndex === -1) {
|
|
31
30
|
logger.warn(`Collection '${collectionSlug}' not found in config.collections`);
|
|
32
31
|
continue;
|
|
33
32
|
}
|
|
34
33
|
const collection = config.collections[collectionIndex];
|
|
35
|
-
// Initialize hooks if needed
|
|
36
34
|
if (!collection.hooks) {
|
|
37
35
|
collection.hooks = {};
|
|
38
36
|
}
|
|
39
|
-
// Determine which hooks to register based on config
|
|
40
37
|
const hooksToRegister = triggerConfig === true ? {
|
|
41
38
|
afterChange: true,
|
|
42
39
|
afterDelete: true,
|
|
43
40
|
afterRead: true
|
|
44
41
|
} : triggerConfig;
|
|
45
|
-
// Register each configured hook
|
|
46
42
|
Object.entries(hooksToRegister).forEach(([hookName, enabled])=>{
|
|
47
43
|
if (!enabled) {
|
|
48
44
|
return;
|
|
49
45
|
}
|
|
50
46
|
const hookKey = hookName;
|
|
51
|
-
// Initialize the hook array if needed
|
|
52
47
|
if (!collection.hooks[hookKey]) {
|
|
53
48
|
collection.hooks[hookKey] = [];
|
|
54
49
|
}
|
|
55
|
-
// Create the automation hook for this specific collection and hook type
|
|
56
50
|
const automationHook = createCollectionTriggerHook(collectionSlug, hookKey);
|
|
57
|
-
// Mark it for debugging
|
|
58
51
|
Object.defineProperty(automationHook, '__isAutomationHook', {
|
|
59
52
|
value: true,
|
|
60
53
|
enumerable: false
|
|
@@ -68,41 +61,34 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
|
|
|
68
61
|
});
|
|
69
62
|
}
|
|
70
63
|
}
|
|
71
|
-
//
|
|
64
|
+
// Register global hooks
|
|
72
65
|
if (config.globals && pluginOptions.globalTriggers) {
|
|
73
66
|
for (const [globalSlug, triggerConfig] of Object.entries(pluginOptions.globalTriggers)){
|
|
74
67
|
if (!triggerConfig) {
|
|
75
68
|
continue;
|
|
76
69
|
}
|
|
77
|
-
// Find the global config that matches
|
|
78
70
|
const globalIndex = config.globals.findIndex((g)=>g.slug === globalSlug);
|
|
79
71
|
if (globalIndex === -1) {
|
|
80
72
|
logger.warn(`Global '${globalSlug}' not found in config.globals`);
|
|
81
73
|
continue;
|
|
82
74
|
}
|
|
83
75
|
const global = config.globals[globalIndex];
|
|
84
|
-
// Initialize hooks if needed
|
|
85
76
|
if (!global.hooks) {
|
|
86
77
|
global.hooks = {};
|
|
87
78
|
}
|
|
88
|
-
// Determine which hooks to register based on config
|
|
89
79
|
const hooksToRegister = triggerConfig === true ? {
|
|
90
80
|
afterChange: true,
|
|
91
81
|
afterRead: true
|
|
92
82
|
} : triggerConfig;
|
|
93
|
-
// Register each configured hook
|
|
94
83
|
Object.entries(hooksToRegister).forEach(([hookName, enabled])=>{
|
|
95
84
|
if (!enabled) {
|
|
96
85
|
return;
|
|
97
86
|
}
|
|
98
87
|
const hookKey = hookName;
|
|
99
|
-
// Initialize the hook array if needed
|
|
100
88
|
if (!global.hooks[hookKey]) {
|
|
101
89
|
global.hooks[hookKey] = [];
|
|
102
90
|
}
|
|
103
|
-
// Create the automation hook for this specific global and hook type
|
|
104
91
|
const automationHook = createGlobalTriggerHook(globalSlug, hookKey);
|
|
105
|
-
// Mark it for debugging
|
|
106
92
|
Object.defineProperty(automationHook, '__isAutomationHook', {
|
|
107
93
|
value: true,
|
|
108
94
|
enumerable: false
|
|
@@ -116,6 +102,7 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
|
|
|
116
102
|
});
|
|
117
103
|
}
|
|
118
104
|
}
|
|
105
|
+
// Register step tasks
|
|
119
106
|
if (!config.jobs) {
|
|
120
107
|
config.jobs = {
|
|
121
108
|
tasks: []
|
|
@@ -126,18 +113,85 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
|
|
|
126
113
|
config.jobs?.tasks?.push(step);
|
|
127
114
|
}
|
|
128
115
|
}
|
|
129
|
-
//
|
|
116
|
+
// Extend payload-jobs collection with automation context fields
|
|
117
|
+
const existingJobsOverrides = config.jobs.jobsCollectionOverrides;
|
|
118
|
+
config.jobs.jobsCollectionOverrides = ({ defaultJobsCollection })=>{
|
|
119
|
+
// Apply any existing overrides first
|
|
120
|
+
const collection = existingJobsOverrides ? existingJobsOverrides({
|
|
121
|
+
defaultJobsCollection
|
|
122
|
+
}) : defaultJobsCollection;
|
|
123
|
+
return {
|
|
124
|
+
...collection,
|
|
125
|
+
fields: [
|
|
126
|
+
...collection.fields,
|
|
127
|
+
// Structured automation context fields for admin UI integration
|
|
128
|
+
{
|
|
129
|
+
name: 'automationWorkflow',
|
|
130
|
+
type: 'relationship',
|
|
131
|
+
relationTo: 'workflows',
|
|
132
|
+
admin: {
|
|
133
|
+
position: 'sidebar',
|
|
134
|
+
readOnly: true,
|
|
135
|
+
description: 'Workflow that created this job'
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'automationWorkflowRun',
|
|
140
|
+
type: 'relationship',
|
|
141
|
+
relationTo: 'workflow-runs',
|
|
142
|
+
admin: {
|
|
143
|
+
position: 'sidebar',
|
|
144
|
+
readOnly: true,
|
|
145
|
+
description: 'Workflow run that created this job'
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'automationTrigger',
|
|
150
|
+
type: 'relationship',
|
|
151
|
+
relationTo: 'automation-triggers',
|
|
152
|
+
admin: {
|
|
153
|
+
position: 'sidebar',
|
|
154
|
+
readOnly: true,
|
|
155
|
+
description: 'Trigger that initiated the workflow'
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'automationStepName',
|
|
160
|
+
type: 'text',
|
|
161
|
+
admin: {
|
|
162
|
+
position: 'sidebar',
|
|
163
|
+
readOnly: true,
|
|
164
|
+
description: 'Name of the workflow step that created this job'
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
],
|
|
168
|
+
admin: {
|
|
169
|
+
...collection.admin,
|
|
170
|
+
listSearchableFields: [
|
|
171
|
+
...collection.admin?.listSearchableFields || []
|
|
172
|
+
],
|
|
173
|
+
defaultColumns: [
|
|
174
|
+
...collection.admin?.defaultColumns || [
|
|
175
|
+
'taskSlug',
|
|
176
|
+
'queue',
|
|
177
|
+
'processing',
|
|
178
|
+
'completedAt'
|
|
179
|
+
]
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
// Set up onInit
|
|
130
185
|
const incomingOnInit = config.onInit;
|
|
131
186
|
config.onInit = async (payload)=>{
|
|
132
|
-
// Execute any existing onInit functions first
|
|
133
187
|
if (incomingOnInit) {
|
|
134
188
|
await incomingOnInit(payload);
|
|
135
189
|
}
|
|
136
|
-
// Initialize the logger with the payload instance
|
|
137
190
|
const logger = initializeLogger(payload);
|
|
138
|
-
logger.info('
|
|
139
|
-
|
|
140
|
-
|
|
191
|
+
logger.info('Automation plugin initialized');
|
|
192
|
+
const collectionCount = Object.keys(pluginOptions.collectionTriggers || {}).length;
|
|
193
|
+
const globalCount = Object.keys(pluginOptions.globalTriggers || {}).length;
|
|
194
|
+
const stepCount = pluginOptions.steps?.length || 0;
|
|
141
195
|
// Seed workflows if configured
|
|
142
196
|
if (pluginOptions.seedWorkflows && pluginOptions.seedWorkflows.length > 0) {
|
|
143
197
|
logger.info(`Seeding ${pluginOptions.seedWorkflows.length} workflows...`);
|
|
@@ -154,44 +208,85 @@ export const workflowsPlugin = (pluginOptions)=>(config)=>{
|
|
|
154
208
|
limit: 1
|
|
155
209
|
});
|
|
156
210
|
if (existingWorkflow.docs.length > 0) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
211
|
+
logger.debug(`Workflow '${seedWorkflow.slug}' already exists, skipping seed`);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
// Create triggers in automation-triggers collection
|
|
215
|
+
const triggerIds = [];
|
|
216
|
+
for(let i = 0; i < seedWorkflow.triggers.length; i++){
|
|
217
|
+
const triggerDef = seedWorkflow.triggers[i];
|
|
218
|
+
const triggerName = `${seedWorkflow.name} - Trigger ${i + 1}`;
|
|
219
|
+
// Build trigger data based on type
|
|
220
|
+
const triggerData = {
|
|
221
|
+
name: triggerName,
|
|
222
|
+
type: triggerDef.type,
|
|
223
|
+
condition: triggerDef.condition
|
|
224
|
+
};
|
|
225
|
+
// Map parameters to trigger fields based on type
|
|
226
|
+
if (triggerDef.parameters) {
|
|
227
|
+
if (triggerDef.type === 'collection-hook') {
|
|
228
|
+
triggerData.collectionSlug = triggerDef.parameters.collectionSlug;
|
|
229
|
+
triggerData.hook = triggerDef.parameters.hook;
|
|
230
|
+
} else if (triggerDef.type === 'global-hook') {
|
|
231
|
+
triggerData.globalSlug = triggerDef.parameters.globalSlug;
|
|
232
|
+
triggerData.hook = triggerDef.parameters.hook;
|
|
233
|
+
} else if (triggerDef.type === 'scheduled') {
|
|
234
|
+
triggerData.schedule = triggerDef.parameters.schedule;
|
|
235
|
+
} else if (triggerDef.type === 'webhook') {
|
|
236
|
+
triggerData.webhookPath = triggerDef.parameters.webhookPath;
|
|
237
|
+
}
|
|
177
238
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
239
|
+
const trigger = await payload.create({
|
|
240
|
+
collection: 'automation-triggers',
|
|
241
|
+
data: triggerData
|
|
242
|
+
});
|
|
243
|
+
triggerIds.push(trigger.id);
|
|
244
|
+
logger.debug(`Created trigger: ${triggerName}`);
|
|
245
|
+
}
|
|
246
|
+
// Create steps in automation-steps collection and build workflow steps array
|
|
247
|
+
const workflowSteps = [];
|
|
248
|
+
for (const stepDef of seedWorkflow.steps){
|
|
249
|
+
const stepName = `${seedWorkflow.name} - ${stepDef.name}`;
|
|
250
|
+
// Create step in automation-steps collection
|
|
251
|
+
const step = await payload.create({
|
|
252
|
+
collection: 'automation-steps',
|
|
182
253
|
data: {
|
|
183
|
-
|
|
184
|
-
|
|
254
|
+
name: stepName,
|
|
255
|
+
type: stepDef.type,
|
|
256
|
+
config: stepDef.input || {}
|
|
185
257
|
}
|
|
186
258
|
});
|
|
187
|
-
logger.
|
|
259
|
+
logger.debug(`Created step: ${stepName}`);
|
|
260
|
+
// Add to workflow steps with relationship ID
|
|
261
|
+
workflowSteps.push({
|
|
262
|
+
step: step.id,
|
|
263
|
+
stepName: stepDef.name,
|
|
264
|
+
inputOverrides: stepDef.input || {},
|
|
265
|
+
condition: stepDef.condition,
|
|
266
|
+
dependencies: stepDef.dependencies?.map((dep)=>({
|
|
267
|
+
stepName: dep
|
|
268
|
+
}))
|
|
269
|
+
});
|
|
188
270
|
}
|
|
271
|
+
// Create the workflow with relationship IDs
|
|
272
|
+
await payload.create({
|
|
273
|
+
collection: 'workflows',
|
|
274
|
+
data: {
|
|
275
|
+
slug: seedWorkflow.slug,
|
|
276
|
+
name: seedWorkflow.name,
|
|
277
|
+
description: seedWorkflow.description,
|
|
278
|
+
triggers: triggerIds,
|
|
279
|
+
steps: workflowSteps,
|
|
280
|
+
readOnly: true
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
logger.info(`Seeded workflow: ${seedWorkflow.name}`);
|
|
189
284
|
} catch (error) {
|
|
190
285
|
logger.error(`Failed to seed workflow '${seedWorkflow.name}':`, error);
|
|
191
286
|
}
|
|
192
287
|
}
|
|
193
288
|
}
|
|
194
|
-
logger.info(
|
|
289
|
+
logger.info(`Plugin configuration: ${collectionCount} collection triggers, ${globalCount} global triggers, ${stepCount} steps`);
|
|
195
290
|
};
|
|
196
291
|
return config;
|
|
197
292
|
};
|
package/dist/plugin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugin/index.ts"],"sourcesContent":["import type {CollectionConfig, Config} from 'payload'\n\nimport type {WorkflowsPluginConfig} from \"./config-types.js\"\n\nimport {createWorkflowCollection} from '../collections/Workflow.js'\nimport {WorkflowRunsCollection} from '../collections/WorkflowRuns.js'\nimport {WorkflowExecutor} from '../core/workflow-executor.js'\nimport {getConfigLogger, initializeLogger} from './logger.js'\nimport {createCollectionTriggerHook} from \"./collection-hook.js\"\nimport {createGlobalTriggerHook} from \"./global-hook.js\"\n\nexport {getLogger} from './logger.js'\n\nconst applyCollectionsConfig = <T extends string>(pluginOptions: WorkflowsPluginConfig<T>, config: Config) => {\n // Add workflow collections\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(\n createWorkflowCollection(pluginOptions),\n WorkflowRunsCollection\n )\n}\n\ntype AnyHook =\n CollectionConfig['hooks'] extends infer H\n ? H extends Record<string, unknown>\n ? NonNullable<H[keyof H]> extends (infer U)[]\n ? U\n : never\n : never\n : never;\n\ntype HookArgs = Parameters<AnyHook>[0]\n\nexport const workflowsPlugin =\n <TSlug extends string>(pluginOptions: WorkflowsPluginConfig<TSlug>) =>\n (config: Config): Config => {\n // If the plugin is disabled, return config unchanged\n if (pluginOptions.enabled === false) {\n return config\n }\n\n applyCollectionsConfig<TSlug>(pluginOptions, config)\n\n // CRITICAL: Modify existing collection configs BEFORE PayloadCMS processes them\n // This is the ONLY time we can add hooks that will actually work\n const logger = getConfigLogger()\n\n if (config.collections && pluginOptions.collectionTriggers) {\n for (const [collectionSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n // Find the collection config that matches\n const collectionIndex = config.collections.findIndex(c => c.slug === collectionSlug)\n if (collectionIndex === -1) {\n logger.warn(`Collection '${collectionSlug}' not found in config.collections`)\n continue\n }\n\n const collection = config.collections[collectionIndex]\n\n // Initialize hooks if needed\n if (!collection.hooks) {\n collection.hooks = {}\n }\n\n // Determine which hooks to register based on config\n const hooksToRegister = triggerConfig === true\n ? {\n afterChange: true,\n afterDelete: true,\n afterRead: true,\n }\n : triggerConfig\n\n // Register each configured hook\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof collection.hooks\n\n // Initialize the hook array if needed\n if (!collection.hooks![hookKey]) {\n collection.hooks![hookKey] = []\n }\n\n // Create the automation hook for this specific collection and hook type\n const automationHook = createCollectionTriggerHook(collectionSlug, hookKey)\n\n // Mark it for debugging\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n // Add the hook to the collection\n ;(collection.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for collection '${collectionSlug}'`)\n })\n }\n }\n\n // Handle global triggers similarly to collection triggers\n if (config.globals && pluginOptions.globalTriggers) {\n for (const [globalSlug, triggerConfig] of Object.entries(pluginOptions.globalTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n // Find the global config that matches\n const globalIndex = config.globals.findIndex(g => g.slug === globalSlug)\n if (globalIndex === -1) {\n logger.warn(`Global '${globalSlug}' not found in config.globals`)\n continue\n }\n\n const global = config.globals[globalIndex]\n\n // Initialize hooks if needed\n if (!global.hooks) {\n global.hooks = {}\n }\n\n // Determine which hooks to register based on config\n const hooksToRegister = triggerConfig === true\n ? {\n afterChange: true,\n afterRead: true,\n }\n : triggerConfig\n\n // Register each configured hook\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof global.hooks\n\n // Initialize the hook array if needed\n if (!global.hooks![hookKey]) {\n global.hooks![hookKey] = []\n }\n\n // Create the automation hook for this specific global and hook type\n const automationHook = createGlobalTriggerHook(globalSlug, hookKey)\n\n // Mark it for debugging\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n // Add the hook to the global\n ;(global.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for global '${globalSlug}'`)\n })\n }\n }\n\n if (!config.jobs) {\n config.jobs = {tasks: []}\n }\n\n for (const step of pluginOptions.steps) {\n if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) {\n config.jobs?.tasks?.push(step)\n }\n }\n\n\n // Set up onInit to initialize features\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n // Execute any existing onInit functions first\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n // Initialize the logger with the payload instance\n const logger = initializeLogger(payload)\n logger.info('Logger initialized with payload instance')\n\n // Log trigger configuration\n logger.info(`Plugin configuration: ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers, ${Object.keys(pluginOptions.globalTriggers || {}).length} global triggers, ${pluginOptions.steps?.length || 0} steps`)\n\n // Seed workflows if configured\n if (pluginOptions.seedWorkflows && pluginOptions.seedWorkflows.length > 0) {\n logger.info(`Seeding ${pluginOptions.seedWorkflows.length} workflows...`)\n\n for (const seedWorkflow of pluginOptions.seedWorkflows) {\n try {\n // Check if workflow already exists by slug\n const existingWorkflow = await payload.find({\n collection: 'workflows',\n where: {\n slug: {\n equals: seedWorkflow.slug,\n },\n },\n limit: 1,\n })\n\n if (existingWorkflow.docs.length > 0) {\n const existing = existingWorkflow.docs[0]\n\n // Detect changes by comparing workflow definition\n const stepsChanged = JSON.stringify(existing.steps) !== JSON.stringify(seedWorkflow.steps)\n const triggersChanged = JSON.stringify(existing.triggers) !== JSON.stringify(seedWorkflow.triggers)\n const nameChanged = existing.name !== seedWorkflow.name\n const descriptionChanged = existing.description !== seedWorkflow.description\n\n const hasChanges = stepsChanged || triggersChanged || nameChanged || descriptionChanged\n\n if (hasChanges) {\n logger.info(`Updating seeded workflow '${seedWorkflow.slug}': ${seedWorkflow.name}`)\n\n await payload.update({\n collection: 'workflows',\n id: existing.id,\n data: {\n ...seedWorkflow,\n readOnly: true,\n },\n })\n\n logger.info(`Updated workflow: ${seedWorkflow.name}`)\n } else {\n logger.debug(`Workflow '${seedWorkflow.slug}' is up to date, skipping`)\n }\n } else {\n // Create the workflow as read-only\n await payload.create({\n collection: 'workflows',\n data: {\n ...seedWorkflow,\n readOnly: true,\n },\n })\n\n logger.info(`Seeded workflow: ${seedWorkflow.name}`)\n }\n } catch (error) {\n logger.error(`Failed to seed workflow '${seedWorkflow.name}':`, error)\n }\n }\n }\n\n logger.info('Plugin initialized successfully - all hooks registered')\n }\n\n return config\n }\n"],"names":["createWorkflowCollection","WorkflowRunsCollection","getConfigLogger","initializeLogger","createCollectionTriggerHook","createGlobalTriggerHook","getLogger","applyCollectionsConfig","pluginOptions","config","collections","push","workflowsPlugin","enabled","logger","collectionTriggers","collectionSlug","triggerConfig","Object","entries","collectionIndex","findIndex","c","slug","warn","collection","hooks","hooksToRegister","afterChange","afterDelete","afterRead","forEach","hookName","hookKey","automationHook","defineProperty","value","enumerable","debug","globals","globalTriggers","globalSlug","globalIndex","g","global","jobs","tasks","step","steps","find","task","incomingOnInit","onInit","payload","info","keys","length","seedWorkflows","seedWorkflow","existingWorkflow","where","equals","limit","docs","existing","stepsChanged","JSON","stringify","triggersChanged","triggers","nameChanged","name","descriptionChanged","description","hasChanges","update","id","data","readOnly","create","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/plugin/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload'\n\nimport type { WorkflowsPluginConfig } from './config-types.js'\n\nimport { createTriggersCollection } from '../collections/Triggers.js'\nimport { createStepsCollection } from '../collections/Steps.js'\nimport { createWorkflowCollection } from '../collections/Workflow.js'\nimport { WorkflowRunsCollection } from '../collections/WorkflowRuns.js'\nimport { getConfigLogger, initializeLogger } from './logger.js'\nimport { createCollectionTriggerHook, createGlobalTriggerHook } from './trigger-hook.js'\n\nexport { getLogger } from './logger.js'\n\nconst applyCollectionsConfig = <T extends string>(\n pluginOptions: WorkflowsPluginConfig<T>,\n config: Config\n) => {\n if (!config.collections) {\n config.collections = []\n }\n\n // Add all automation collections\n config.collections.push(\n createTriggersCollection(pluginOptions),\n createStepsCollection(pluginOptions.steps),\n createWorkflowCollection(),\n WorkflowRunsCollection\n )\n}\n\ntype AnyHook =\n CollectionConfig['hooks'] extends infer H\n ? H extends Record<string, unknown>\n ? NonNullable<H[keyof H]> extends (infer U)[]\n ? U\n : never\n : never\n : never\n\nexport const workflowsPlugin =\n <TSlug extends string>(pluginOptions: WorkflowsPluginConfig<TSlug>) =>\n (config: Config): Config => {\n // If the plugin is disabled, return config unchanged\n if (pluginOptions.enabled === false) {\n return config\n }\n\n applyCollectionsConfig<TSlug>(pluginOptions, config)\n\n const logger = getConfigLogger()\n\n // Register collection hooks\n if (config.collections && pluginOptions.collectionTriggers) {\n for (const [collectionSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n const collectionIndex = config.collections.findIndex(c => c.slug === collectionSlug)\n if (collectionIndex === -1) {\n logger.warn(`Collection '${collectionSlug}' not found in config.collections`)\n continue\n }\n\n const collection = config.collections[collectionIndex]\n\n if (!collection.hooks) {\n collection.hooks = {}\n }\n\n const hooksToRegister = triggerConfig === true\n ? { afterChange: true, afterDelete: true, afterRead: true }\n : triggerConfig\n\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof collection.hooks\n\n if (!collection.hooks![hookKey]) {\n collection.hooks![hookKey] = []\n }\n\n const automationHook = createCollectionTriggerHook(collectionSlug, hookKey)\n\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n ;(collection.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for collection '${collectionSlug}'`)\n })\n }\n }\n\n // Register global hooks\n if (config.globals && pluginOptions.globalTriggers) {\n for (const [globalSlug, triggerConfig] of Object.entries(pluginOptions.globalTriggers)) {\n if (!triggerConfig) {\n continue\n }\n\n const globalIndex = config.globals.findIndex(g => g.slug === globalSlug)\n if (globalIndex === -1) {\n logger.warn(`Global '${globalSlug}' not found in config.globals`)\n continue\n }\n\n const global = config.globals[globalIndex]\n\n if (!global.hooks) {\n global.hooks = {}\n }\n\n const hooksToRegister = triggerConfig === true\n ? { afterChange: true, afterRead: true }\n : triggerConfig\n\n Object.entries(hooksToRegister).forEach(([hookName, enabled]) => {\n if (!enabled) {\n return\n }\n\n const hookKey = hookName as keyof typeof global.hooks\n\n if (!global.hooks![hookKey]) {\n global.hooks![hookKey] = []\n }\n\n const automationHook = createGlobalTriggerHook(globalSlug, hookKey)\n\n Object.defineProperty(automationHook, '__isAutomationHook', {\n value: true,\n enumerable: false\n })\n Object.defineProperty(automationHook, '__hookType', {\n value: hookKey,\n enumerable: false\n })\n\n ;(global.hooks![hookKey] as Array<unknown>).push(automationHook)\n\n logger.debug(`Registered ${hookKey} hook for global '${globalSlug}'`)\n })\n }\n }\n\n // Register step tasks\n if (!config.jobs) {\n config.jobs = { tasks: [] }\n }\n\n for (const step of pluginOptions.steps) {\n if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) {\n config.jobs?.tasks?.push(step)\n }\n }\n\n // Extend payload-jobs collection with automation context fields\n const existingJobsOverrides = config.jobs.jobsCollectionOverrides\n config.jobs.jobsCollectionOverrides = ({ defaultJobsCollection }) => {\n // Apply any existing overrides first\n const collection = existingJobsOverrides\n ? existingJobsOverrides({ defaultJobsCollection })\n : defaultJobsCollection\n\n return {\n ...collection,\n fields: [\n ...collection.fields,\n // Structured automation context fields for admin UI integration\n {\n name: 'automationWorkflow',\n type: 'relationship',\n relationTo: 'workflows',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Workflow that created this job',\n },\n },\n {\n name: 'automationWorkflowRun',\n type: 'relationship',\n relationTo: 'workflow-runs',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Workflow run that created this job',\n },\n },\n {\n name: 'automationTrigger',\n type: 'relationship',\n relationTo: 'automation-triggers',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Trigger that initiated the workflow',\n },\n },\n {\n name: 'automationStepName',\n type: 'text',\n admin: {\n position: 'sidebar',\n readOnly: true,\n description: 'Name of the workflow step that created this job',\n },\n },\n ],\n admin: {\n ...collection.admin,\n listSearchableFields: [\n ...(collection.admin?.listSearchableFields || []),\n ],\n defaultColumns: [\n ...(collection.admin?.defaultColumns || ['taskSlug', 'queue', 'processing', 'completedAt']),\n ],\n },\n }\n }\n\n // Set up onInit\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n const logger = initializeLogger(payload)\n logger.info('Automation plugin initialized')\n\n const collectionCount = Object.keys(pluginOptions.collectionTriggers || {}).length\n const globalCount = Object.keys(pluginOptions.globalTriggers || {}).length\n const stepCount = pluginOptions.steps?.length || 0\n\n // Seed workflows if configured\n if (pluginOptions.seedWorkflows && pluginOptions.seedWorkflows.length > 0) {\n logger.info(`Seeding ${pluginOptions.seedWorkflows.length} workflows...`)\n\n for (const seedWorkflow of pluginOptions.seedWorkflows) {\n try {\n // Check if workflow already exists by slug\n const existingWorkflow = await payload.find({\n collection: 'workflows',\n where: {\n slug: {\n equals: seedWorkflow.slug,\n },\n },\n limit: 1,\n })\n\n if (existingWorkflow.docs.length > 0) {\n logger.debug(`Workflow '${seedWorkflow.slug}' already exists, skipping seed`)\n continue\n }\n\n // Create triggers in automation-triggers collection\n const triggerIds: (string | number)[] = []\n for (let i = 0; i < seedWorkflow.triggers.length; i++) {\n const triggerDef = seedWorkflow.triggers[i]\n const triggerName = `${seedWorkflow.name} - Trigger ${i + 1}`\n\n // Build trigger data based on type\n const triggerData: Record<string, unknown> = {\n name: triggerName,\n type: triggerDef.type,\n condition: triggerDef.condition,\n }\n\n // Map parameters to trigger fields based on type\n if (triggerDef.parameters) {\n if (triggerDef.type === 'collection-hook') {\n triggerData.collectionSlug = triggerDef.parameters.collectionSlug\n triggerData.hook = triggerDef.parameters.hook\n } else if (triggerDef.type === 'global-hook') {\n triggerData.globalSlug = triggerDef.parameters.globalSlug\n triggerData.hook = triggerDef.parameters.hook\n } else if (triggerDef.type === 'scheduled') {\n triggerData.schedule = triggerDef.parameters.schedule\n } else if (triggerDef.type === 'webhook') {\n triggerData.webhookPath = triggerDef.parameters.webhookPath\n }\n }\n\n const trigger = await payload.create({\n collection: 'automation-triggers',\n data: triggerData,\n })\n triggerIds.push(trigger.id)\n logger.debug(`Created trigger: ${triggerName}`)\n }\n\n // Create steps in automation-steps collection and build workflow steps array\n const workflowSteps: Array<{\n step: string | number\n stepName: string\n inputOverrides: Record<string, unknown>\n condition?: string\n dependencies?: Array<{ stepName: string }>\n }> = []\n\n for (const stepDef of seedWorkflow.steps) {\n const stepName = `${seedWorkflow.name} - ${stepDef.name}`\n\n // Create step in automation-steps collection\n const step = await payload.create({\n collection: 'automation-steps',\n data: {\n name: stepName,\n type: stepDef.type,\n config: stepDef.input || {},\n },\n })\n logger.debug(`Created step: ${stepName}`)\n\n // Add to workflow steps with relationship ID\n workflowSteps.push({\n step: step.id,\n stepName: stepDef.name,\n inputOverrides: stepDef.input || {},\n condition: stepDef.condition,\n dependencies: stepDef.dependencies?.map(dep => ({ stepName: dep })),\n })\n }\n\n // Create the workflow with relationship IDs\n await payload.create({\n collection: 'workflows',\n data: {\n slug: seedWorkflow.slug,\n name: seedWorkflow.name,\n description: seedWorkflow.description,\n triggers: triggerIds,\n steps: workflowSteps,\n readOnly: true,\n },\n })\n\n logger.info(`Seeded workflow: ${seedWorkflow.name}`)\n } catch (error) {\n logger.error(`Failed to seed workflow '${seedWorkflow.name}':`, error)\n }\n }\n }\n\n logger.info(`Plugin configuration: ${collectionCount} collection triggers, ${globalCount} global triggers, ${stepCount} steps`\n )\n }\n\n return config\n }\n"],"names":["createTriggersCollection","createStepsCollection","createWorkflowCollection","WorkflowRunsCollection","getConfigLogger","initializeLogger","createCollectionTriggerHook","createGlobalTriggerHook","getLogger","applyCollectionsConfig","pluginOptions","config","collections","push","steps","workflowsPlugin","enabled","logger","collectionTriggers","collectionSlug","triggerConfig","Object","entries","collectionIndex","findIndex","c","slug","warn","collection","hooks","hooksToRegister","afterChange","afterDelete","afterRead","forEach","hookName","hookKey","automationHook","defineProperty","value","enumerable","debug","globals","globalTriggers","globalSlug","globalIndex","g","global","jobs","tasks","step","find","task","existingJobsOverrides","jobsCollectionOverrides","defaultJobsCollection","fields","name","type","relationTo","admin","position","readOnly","description","listSearchableFields","defaultColumns","incomingOnInit","onInit","payload","info","collectionCount","keys","length","globalCount","stepCount","seedWorkflows","seedWorkflow","existingWorkflow","where","equals","limit","docs","triggerIds","i","triggers","triggerDef","triggerName","triggerData","condition","parameters","hook","schedule","webhookPath","trigger","create","data","id","workflowSteps","stepDef","stepName","input","inputOverrides","dependencies","map","dep","error"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type TriggerType = 'collection' | 'global';
|
|
2
|
+
export interface TriggerConfig {
|
|
3
|
+
type: TriggerType;
|
|
4
|
+
slug: string;
|
|
5
|
+
hookType: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Creates a unified hook handler for both collection and global triggers.
|
|
9
|
+
* Works with the new relationship-based data model where triggers are a separate collection.
|
|
10
|
+
*/
|
|
11
|
+
export declare const createTriggerHook: (config: TriggerConfig) => (args: any) => Promise<void>;
|
|
12
|
+
export declare const createCollectionTriggerHook: (collectionSlug: string, hookType: string) => (args: any) => Promise<void>;
|
|
13
|
+
export declare const createGlobalTriggerHook: (globalSlug: string, hookType: string) => (args: any) => Promise<void>;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { WorkflowExecutor } from '../core/workflow-executor.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a unified hook handler for both collection and global triggers.
|
|
4
|
+
* Works with the new relationship-based data model where triggers are a separate collection.
|
|
5
|
+
*/ export const createTriggerHook = (config)=>{
|
|
6
|
+
const { type, slug, hookType } = config;
|
|
7
|
+
// Build context based on trigger type
|
|
8
|
+
const buildContext = (args, firedTrigger)=>({
|
|
9
|
+
steps: {},
|
|
10
|
+
trigger: {
|
|
11
|
+
...args,
|
|
12
|
+
type,
|
|
13
|
+
firedTrigger,
|
|
14
|
+
...type === 'collection' ? {
|
|
15
|
+
collection: slug
|
|
16
|
+
} : {
|
|
17
|
+
global: slug,
|
|
18
|
+
operation: hookType
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return async function automationTriggerHook(args) {
|
|
23
|
+
const req = 'req' in args ? args.req : 'args' in args ? args.args.req : undefined;
|
|
24
|
+
if (!req) {
|
|
25
|
+
throw new Error(`No request object found in ${type} hook arguments`);
|
|
26
|
+
}
|
|
27
|
+
const payload = req.payload;
|
|
28
|
+
const logger = payload.logger;
|
|
29
|
+
try {
|
|
30
|
+
logger.info({
|
|
31
|
+
triggerType: type,
|
|
32
|
+
slug,
|
|
33
|
+
hookType
|
|
34
|
+
}, `${type} automation hook triggered`);
|
|
35
|
+
const executor = new WorkflowExecutor(payload, logger);
|
|
36
|
+
// Step 1: Find all triggers that match this hook event
|
|
37
|
+
const triggerQuery = type === 'collection' ? {
|
|
38
|
+
type: {
|
|
39
|
+
equals: 'collection-hook'
|
|
40
|
+
},
|
|
41
|
+
collectionSlug: {
|
|
42
|
+
equals: slug
|
|
43
|
+
},
|
|
44
|
+
hook: {
|
|
45
|
+
equals: hookType
|
|
46
|
+
}
|
|
47
|
+
} : {
|
|
48
|
+
type: {
|
|
49
|
+
equals: 'global-hook'
|
|
50
|
+
},
|
|
51
|
+
globalSlug: {
|
|
52
|
+
equals: slug
|
|
53
|
+
},
|
|
54
|
+
hook: {
|
|
55
|
+
equals: hookType
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const { docs: matchingTriggers } = await payload.find({
|
|
59
|
+
collection: 'automation-triggers',
|
|
60
|
+
depth: 0,
|
|
61
|
+
limit: 100,
|
|
62
|
+
where: triggerQuery
|
|
63
|
+
});
|
|
64
|
+
if (matchingTriggers.length === 0) {
|
|
65
|
+
logger.debug({
|
|
66
|
+
triggerType: type,
|
|
67
|
+
slug,
|
|
68
|
+
hookType
|
|
69
|
+
}, 'No matching triggers found');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const triggerIds = matchingTriggers.map((t)=>t.id);
|
|
73
|
+
// Step 2: Find all enabled workflows that reference any of these triggers
|
|
74
|
+
const { docs: workflows } = await payload.find({
|
|
75
|
+
collection: 'workflows',
|
|
76
|
+
depth: 2,
|
|
77
|
+
limit: 100,
|
|
78
|
+
where: {
|
|
79
|
+
enabled: {
|
|
80
|
+
equals: true
|
|
81
|
+
},
|
|
82
|
+
triggers: {
|
|
83
|
+
in: triggerIds
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
if (workflows.length === 0) {
|
|
88
|
+
logger.debug({
|
|
89
|
+
triggerType: type,
|
|
90
|
+
slug,
|
|
91
|
+
hookType,
|
|
92
|
+
triggerIds
|
|
93
|
+
}, 'No enabled workflows found for matching triggers');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Step 3: Execute each matching workflow
|
|
97
|
+
for (const workflow of workflows){
|
|
98
|
+
// Find which trigger actually fired (for tracking in WorkflowRuns)
|
|
99
|
+
const firedTrigger = matchingTriggers.find((trigger)=>{
|
|
100
|
+
const workflowTriggerIds = (workflow.triggers || []).map((t)=>typeof t === 'object' ? t.id : t);
|
|
101
|
+
return workflowTriggerIds.includes(trigger.id);
|
|
102
|
+
});
|
|
103
|
+
if (!firedTrigger) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const context = buildContext(args, firedTrigger);
|
|
107
|
+
// Evaluate trigger condition if present
|
|
108
|
+
if (firedTrigger.condition) {
|
|
109
|
+
try {
|
|
110
|
+
const conditionMet = await executor.evaluateCondition(firedTrigger.condition, context);
|
|
111
|
+
if (!conditionMet) {
|
|
112
|
+
logger.debug({
|
|
113
|
+
workflowId: workflow.id,
|
|
114
|
+
triggerId: firedTrigger.id,
|
|
115
|
+
condition: firedTrigger.condition
|
|
116
|
+
}, 'Workflow skipped due to unmet trigger condition');
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
} catch (error) {
|
|
120
|
+
logger.error({
|
|
121
|
+
workflowId: workflow.id,
|
|
122
|
+
triggerId: firedTrigger.id,
|
|
123
|
+
condition: firedTrigger.condition,
|
|
124
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
125
|
+
}, 'Failed to evaluate trigger condition');
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
await executor.execute(workflow, context, req, firedTrigger);
|
|
131
|
+
logger.info({
|
|
132
|
+
workflowId: workflow.id,
|
|
133
|
+
workflowName: workflow.name,
|
|
134
|
+
triggerId: firedTrigger.id,
|
|
135
|
+
triggerName: firedTrigger.name,
|
|
136
|
+
triggerType: type,
|
|
137
|
+
slug,
|
|
138
|
+
hookType
|
|
139
|
+
}, 'Workflow executed successfully');
|
|
140
|
+
} catch (error) {
|
|
141
|
+
logger.error({
|
|
142
|
+
workflowId: workflow.id,
|
|
143
|
+
workflowName: workflow.name,
|
|
144
|
+
triggerId: firedTrigger.id,
|
|
145
|
+
triggerName: firedTrigger.name,
|
|
146
|
+
triggerType: type,
|
|
147
|
+
slug,
|
|
148
|
+
hookType,
|
|
149
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
150
|
+
}, 'Workflow execution failed');
|
|
151
|
+
// Don't throw to prevent breaking the original operation
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
logger.info({
|
|
155
|
+
triggerType: type,
|
|
156
|
+
slug,
|
|
157
|
+
hookType,
|
|
158
|
+
workflowCount: workflows.length
|
|
159
|
+
}, `${type} workflow execution completed`);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
logger.error({
|
|
162
|
+
triggerType: type,
|
|
163
|
+
slug,
|
|
164
|
+
hookType,
|
|
165
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
166
|
+
errorStack: error instanceof Error ? error.stack : undefined
|
|
167
|
+
}, `${type} hook execution failed`);
|
|
168
|
+
// Don't throw to prevent breaking the original operation
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
// Convenience functions for creating hooks
|
|
173
|
+
export const createCollectionTriggerHook = (collectionSlug, hookType)=>createTriggerHook({
|
|
174
|
+
type: 'collection',
|
|
175
|
+
slug: collectionSlug,
|
|
176
|
+
hookType
|
|
177
|
+
});
|
|
178
|
+
export const createGlobalTriggerHook = (globalSlug, hookType)=>createTriggerHook({
|
|
179
|
+
type: 'global',
|
|
180
|
+
slug: globalSlug,
|
|
181
|
+
hookType
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
//# sourceMappingURL=trigger-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/plugin/trigger-hook.ts"],"sourcesContent":["import { WorkflowExecutor } from '../core/workflow-executor.js'\n\nexport type TriggerType = 'collection' | 'global'\n\nexport interface TriggerConfig {\n type: TriggerType\n slug: string\n hookType: string\n}\n\n/**\n * Creates a unified hook handler for both collection and global triggers.\n * Works with the new relationship-based data model where triggers are a separate collection.\n */\nexport const createTriggerHook = (config: TriggerConfig) => {\n const { type, slug, hookType } = config\n\n // Build context based on trigger type\n const buildContext = (args: any, firedTrigger?: any) => ({\n steps: {},\n trigger: {\n ...args,\n type,\n firedTrigger,\n ...(type === 'collection'\n ? { collection: slug }\n : { global: slug, operation: hookType }\n )\n }\n })\n\n return async function automationTriggerHook(args: any) {\n const req = 'req' in args ? args.req :\n 'args' in args ? args.args.req :\n undefined\n\n if (!req) {\n throw new Error(`No request object found in ${type} hook arguments`)\n }\n\n const payload = req.payload\n const logger = payload.logger\n\n try {\n logger.info({\n triggerType: type,\n slug,\n hookType\n }, `${type} automation hook triggered`)\n\n const executor = new WorkflowExecutor(payload, logger)\n\n // Step 1: Find all triggers that match this hook event\n const triggerQuery = type === 'collection'\n ? {\n type: { equals: 'collection-hook' },\n collectionSlug: { equals: slug },\n hook: { equals: hookType }\n }\n : {\n type: { equals: 'global-hook' },\n globalSlug: { equals: slug },\n hook: { equals: hookType }\n }\n\n const { docs: matchingTriggers } = await payload.find({\n collection: 'automation-triggers',\n depth: 0,\n limit: 100,\n where: triggerQuery\n })\n\n if (matchingTriggers.length === 0) {\n logger.debug({\n triggerType: type,\n slug,\n hookType\n }, 'No matching triggers found')\n return\n }\n\n const triggerIds = matchingTriggers.map((t: { id: string | number }) => t.id)\n\n // Step 2: Find all enabled workflows that reference any of these triggers\n const { docs: workflows } = await payload.find({\n collection: 'workflows',\n depth: 2, // Load trigger and step details\n limit: 100,\n where: {\n enabled: { equals: true },\n triggers: { in: triggerIds }\n }\n })\n\n if (workflows.length === 0) {\n logger.debug({\n triggerType: type,\n slug,\n hookType,\n triggerIds\n }, 'No enabled workflows found for matching triggers')\n return\n }\n\n // Step 3: Execute each matching workflow\n for (const workflow of workflows) {\n // Find which trigger actually fired (for tracking in WorkflowRuns)\n const firedTrigger = matchingTriggers.find((trigger: { id: string | number }) => {\n const workflowTriggerIds = (workflow.triggers || []).map((t: any) =>\n typeof t === 'object' ? t.id : t\n )\n return workflowTriggerIds.includes(trigger.id)\n })\n\n if (!firedTrigger) {\n continue\n }\n\n const context = buildContext(args, firedTrigger)\n\n // Evaluate trigger condition if present\n if (firedTrigger.condition) {\n try {\n const conditionMet = await executor.evaluateCondition(firedTrigger.condition, context)\n if (!conditionMet) {\n logger.debug({\n workflowId: workflow.id,\n triggerId: firedTrigger.id,\n condition: firedTrigger.condition\n }, 'Workflow skipped due to unmet trigger condition')\n continue\n }\n } catch (error) {\n logger.error({\n workflowId: workflow.id,\n triggerId: firedTrigger.id,\n condition: firedTrigger.condition,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to evaluate trigger condition')\n continue\n }\n }\n\n try {\n await executor.execute(workflow as any, context, req, firedTrigger)\n logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name,\n triggerId: firedTrigger.id,\n triggerName: firedTrigger.name,\n triggerType: type,\n slug,\n hookType\n }, 'Workflow executed successfully')\n } catch (error) {\n logger.error({\n workflowId: workflow.id,\n workflowName: workflow.name,\n triggerId: firedTrigger.id,\n triggerName: firedTrigger.name,\n triggerType: type,\n slug,\n hookType,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Workflow execution failed')\n // Don't throw to prevent breaking the original operation\n }\n }\n\n logger.info({\n triggerType: type,\n slug,\n hookType,\n workflowCount: workflows.length\n }, `${type} workflow execution completed`)\n\n } catch (error) {\n logger.error({\n triggerType: type,\n slug,\n hookType,\n error: error instanceof Error ? error.message : 'Unknown error',\n errorStack: error instanceof Error ? error.stack : undefined\n }, `${type} hook execution failed`)\n // Don't throw to prevent breaking the original operation\n }\n }\n}\n\n// Convenience functions for creating hooks\nexport const createCollectionTriggerHook = (collectionSlug: string, hookType: string) =>\n createTriggerHook({ type: 'collection', slug: collectionSlug, hookType })\n\nexport const createGlobalTriggerHook = (globalSlug: string, hookType: string) =>\n createTriggerHook({ type: 'global', slug: globalSlug, hookType })\n"],"names":["WorkflowExecutor","createTriggerHook","config","type","slug","hookType","buildContext","args","firedTrigger","steps","trigger","collection","global","operation","automationTriggerHook","req","undefined","Error","payload","logger","info","triggerType","executor","triggerQuery","equals","collectionSlug","hook","globalSlug","docs","matchingTriggers","find","depth","limit","where","length","debug","triggerIds","map","t","id","workflows","enabled","triggers","in","workflow","workflowTriggerIds","includes","context","condition","conditionMet","evaluateCondition","workflowId","triggerId","error","message","execute","workflowName","name","triggerName","workflowCount","errorStack","stack","createCollectionTriggerHook","createGlobalTriggerHook"],"mappings":"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"}
|