@xtr-dev/payload-automation 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +73 -0
  2. package/dist/collections/Workflow.d.ts +3 -0
  3. package/dist/collections/Workflow.js +223 -0
  4. package/dist/collections/Workflow.js.map +1 -0
  5. package/dist/collections/WorkflowRuns.d.ts +2 -0
  6. package/dist/collections/WorkflowRuns.js +157 -0
  7. package/dist/collections/WorkflowRuns.js.map +1 -0
  8. package/dist/components/TriggerWorkflowButton.d.ts +7 -0
  9. package/dist/components/TriggerWorkflowButton.js +46 -0
  10. package/dist/components/TriggerWorkflowButton.js.map +1 -0
  11. package/dist/core/trigger-custom-workflow.d.ts +52 -0
  12. package/dist/core/trigger-custom-workflow.js +205 -0
  13. package/dist/core/trigger-custom-workflow.js.map +1 -0
  14. package/dist/core/workflow-executor.d.ts +86 -0
  15. package/dist/core/workflow-executor.js +456 -0
  16. package/dist/core/workflow-executor.js.map +1 -0
  17. package/dist/exports/client.d.ts +1 -0
  18. package/dist/exports/client.js +7 -0
  19. package/dist/exports/client.js.map +1 -0
  20. package/dist/exports/fields.d.ts +1 -0
  21. package/dist/exports/fields.js +6 -0
  22. package/dist/exports/fields.js.map +1 -0
  23. package/dist/exports/rsc.d.ts +1 -0
  24. package/dist/exports/rsc.js +3 -0
  25. package/dist/exports/rsc.js.map +1 -0
  26. package/dist/exports/views.d.ts +1 -0
  27. package/dist/exports/views.js +7 -0
  28. package/dist/exports/views.js.map +1 -0
  29. package/dist/index.d.ts +7 -0
  30. package/dist/index.js +8 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/plugin/config-types.d.ts +21 -0
  33. package/dist/plugin/config-types.js +3 -0
  34. package/dist/plugin/config-types.js.map +1 -0
  35. package/dist/plugin/cron-scheduler.d.ts +32 -0
  36. package/dist/plugin/cron-scheduler.js +537 -0
  37. package/dist/plugin/cron-scheduler.js.map +1 -0
  38. package/dist/plugin/index.d.ts +4 -0
  39. package/dist/plugin/index.js +66 -0
  40. package/dist/plugin/index.js.map +1 -0
  41. package/dist/plugin/init-collection-hooks.d.ts +4 -0
  42. package/dist/plugin/init-collection-hooks.js +63 -0
  43. package/dist/plugin/init-collection-hooks.js.map +1 -0
  44. package/dist/plugin/init-global-hooks.d.ts +3 -0
  45. package/dist/plugin/init-global-hooks.js +83 -0
  46. package/dist/plugin/init-global-hooks.js.map +1 -0
  47. package/dist/plugin/init-step-tasks.d.ts +3 -0
  48. package/dist/plugin/init-step-tasks.js +8 -0
  49. package/dist/plugin/init-step-tasks.js.map +1 -0
  50. package/dist/plugin/init-webhook.d.ts +2 -0
  51. package/dist/plugin/init-webhook.js +154 -0
  52. package/dist/plugin/init-webhook.js.map +1 -0
  53. package/dist/plugin/init-workflow-hooks.d.ts +6 -0
  54. package/dist/plugin/init-workflow-hooks.js +46 -0
  55. package/dist/plugin/init-workflow-hooks.js.map +1 -0
  56. package/dist/plugin/logger.d.ts +20 -0
  57. package/dist/plugin/logger.js +47 -0
  58. package/dist/plugin/logger.js.map +1 -0
  59. package/dist/steps/create-document-handler.d.ts +2 -0
  60. package/dist/steps/create-document-handler.js +36 -0
  61. package/dist/steps/create-document-handler.js.map +1 -0
  62. package/dist/steps/create-document.d.ts +46 -0
  63. package/dist/steps/create-document.js +55 -0
  64. package/dist/steps/create-document.js.map +1 -0
  65. package/dist/steps/delete-document-handler.d.ts +2 -0
  66. package/dist/steps/delete-document-handler.js +62 -0
  67. package/dist/steps/delete-document-handler.js.map +1 -0
  68. package/dist/steps/delete-document.d.ts +39 -0
  69. package/dist/steps/delete-document.js +47 -0
  70. package/dist/steps/delete-document.js.map +1 -0
  71. package/dist/steps/http-request-handler.d.ts +2 -0
  72. package/dist/steps/http-request-handler.js +14 -0
  73. package/dist/steps/http-request-handler.js.map +1 -0
  74. package/dist/steps/http-request.d.ts +12 -0
  75. package/dist/steps/http-request.js +19 -0
  76. package/dist/steps/http-request.js.map +1 -0
  77. package/dist/steps/index.d.ts +12 -0
  78. package/dist/steps/index.js +14 -0
  79. package/dist/steps/index.js.map +1 -0
  80. package/dist/steps/read-document-handler.d.ts +2 -0
  81. package/dist/steps/read-document-handler.js +53 -0
  82. package/dist/steps/read-document-handler.js.map +1 -0
  83. package/dist/steps/read-document.d.ts +46 -0
  84. package/dist/steps/read-document.js +75 -0
  85. package/dist/steps/read-document.js.map +1 -0
  86. package/dist/steps/send-email-handler.d.ts +2 -0
  87. package/dist/steps/send-email-handler.js +48 -0
  88. package/dist/steps/send-email-handler.js.map +1 -0
  89. package/dist/steps/send-email.d.ts +44 -0
  90. package/dist/steps/send-email.js +78 -0
  91. package/dist/steps/send-email.js.map +1 -0
  92. package/dist/steps/update-document-handler.d.ts +2 -0
  93. package/dist/steps/update-document-handler.js +40 -0
  94. package/dist/steps/update-document-handler.js.map +1 -0
  95. package/dist/steps/update-document.d.ts +46 -0
  96. package/dist/steps/update-document.js +63 -0
  97. package/dist/steps/update-document.js.map +1 -0
  98. package/package.json +133 -0
@@ -0,0 +1,456 @@
1
+ import { JSONPath } from 'jsonpath-plus';
2
+ export class WorkflowExecutor {
3
+ payload;
4
+ logger;
5
+ constructor(payload, logger){
6
+ this.payload = payload;
7
+ this.logger = logger;
8
+ }
9
+ /**
10
+ * Evaluate a step condition using JSONPath
11
+ */ evaluateStepCondition(condition, context) {
12
+ return this.evaluateCondition(condition, context);
13
+ }
14
+ /**
15
+ * Execute a single workflow step
16
+ */ async executeStep(step, stepIndex, context, req, workflowRunId) {
17
+ const stepName = step.name || 'step-' + stepIndex;
18
+ this.logger.info({
19
+ hasStep: 'step' in step,
20
+ step: JSON.stringify(step),
21
+ stepName
22
+ }, 'Executing step');
23
+ // Check step condition if present
24
+ if (step.condition) {
25
+ const conditionMet = this.evaluateStepCondition(step.condition, context);
26
+ if (!conditionMet) {
27
+ this.logger.info({
28
+ condition: step.condition,
29
+ stepName
30
+ }, 'Step condition not met, skipping');
31
+ // Mark step as completed but skipped
32
+ context.steps[stepName] = {
33
+ error: undefined,
34
+ input: undefined,
35
+ output: {
36
+ reason: 'Condition not met',
37
+ skipped: true
38
+ },
39
+ state: 'succeeded'
40
+ };
41
+ // Update workflow run context if needed
42
+ if (workflowRunId) {
43
+ await this.updateWorkflowRunContext(workflowRunId, context, req);
44
+ }
45
+ return;
46
+ }
47
+ this.logger.info({
48
+ condition: step.condition,
49
+ stepName
50
+ }, 'Step condition met, proceeding with execution');
51
+ }
52
+ // Initialize step context
53
+ context.steps[stepName] = {
54
+ error: undefined,
55
+ input: undefined,
56
+ output: undefined,
57
+ state: 'running'
58
+ };
59
+ // Move taskSlug declaration outside try block so it's accessible in catch
60
+ const taskSlug = step.step // Use the 'step' field for task type
61
+ ;
62
+ try {
63
+ // Resolve input data using JSONPath
64
+ const resolvedInput = this.resolveStepInput(step.input || {}, context);
65
+ context.steps[stepName].input = resolvedInput;
66
+ if (!taskSlug) {
67
+ throw new Error(`Step ${stepName} is missing a task type`);
68
+ }
69
+ this.logger.info({
70
+ hasInput: !!resolvedInput,
71
+ hasReq: !!req,
72
+ stepName,
73
+ taskSlug
74
+ }, 'Queueing task');
75
+ const job = await this.payload.jobs.queue({
76
+ input: resolvedInput,
77
+ req,
78
+ task: taskSlug
79
+ });
80
+ // Run the job immediately
81
+ await this.payload.jobs.run({
82
+ limit: 1,
83
+ req
84
+ });
85
+ // Get the job result
86
+ const completedJob = await this.payload.findByID({
87
+ id: job.id,
88
+ collection: 'payload-jobs',
89
+ req
90
+ });
91
+ const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried];
92
+ const isComplete = taskStatus?.complete === true;
93
+ const hasError = completedJob.hasError || !isComplete;
94
+ // Extract error information from job if available
95
+ let errorMessage;
96
+ if (hasError) {
97
+ // Try to get error from the latest log entry
98
+ if (completedJob.log && completedJob.log.length > 0) {
99
+ const latestLog = completedJob.log[completedJob.log.length - 1];
100
+ errorMessage = latestLog.error?.message || latestLog.error;
101
+ }
102
+ // Fallback to top-level error
103
+ if (!errorMessage && completedJob.error) {
104
+ errorMessage = completedJob.error.message || completedJob.error;
105
+ }
106
+ // Final fallback to generic message
107
+ if (!errorMessage) {
108
+ errorMessage = `Task ${taskSlug} failed without detailed error information`;
109
+ }
110
+ }
111
+ const result = {
112
+ error: errorMessage,
113
+ output: taskStatus?.output || {},
114
+ state: isComplete ? 'succeeded' : 'failed'
115
+ };
116
+ // Store the output and error
117
+ context.steps[stepName].output = result.output;
118
+ context.steps[stepName].state = result.state;
119
+ if (result.error) {
120
+ context.steps[stepName].error = result.error;
121
+ }
122
+ this.logger.debug({
123
+ context
124
+ }, 'Step execution context');
125
+ if (result.state !== 'succeeded') {
126
+ throw new Error(result.error || `Step ${stepName} failed`);
127
+ }
128
+ this.logger.info({
129
+ output: result.output,
130
+ stepName
131
+ }, 'Step completed');
132
+ // Update workflow run with current step results if workflowRunId is provided
133
+ if (workflowRunId) {
134
+ await this.updateWorkflowRunContext(workflowRunId, context, req);
135
+ }
136
+ } catch (error) {
137
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
138
+ context.steps[stepName].state = 'failed';
139
+ context.steps[stepName].error = errorMessage;
140
+ this.logger.error({
141
+ error: errorMessage,
142
+ input: context.steps[stepName].input,
143
+ stepName,
144
+ taskSlug
145
+ }, 'Step execution failed');
146
+ // Update workflow run with current step results if workflowRunId is provided
147
+ if (workflowRunId) {
148
+ try {
149
+ await this.updateWorkflowRunContext(workflowRunId, context, req);
150
+ } catch (updateError) {
151
+ this.logger.error({
152
+ error: updateError instanceof Error ? updateError.message : 'Unknown error',
153
+ stepName
154
+ }, 'Failed to update workflow run context after step failure');
155
+ }
156
+ }
157
+ throw error;
158
+ }
159
+ }
160
+ /**
161
+ * Resolve step execution order based on dependencies
162
+ */ resolveExecutionOrder(steps) {
163
+ const stepMap = new Map();
164
+ const dependencyGraph = new Map();
165
+ const indegree = new Map();
166
+ // Build the step map and dependency graph
167
+ for (const step of steps){
168
+ const stepName = step.name || `step-${steps.indexOf(step)}`;
169
+ const dependencies = step.dependencies || [];
170
+ stepMap.set(stepName, {
171
+ ...step,
172
+ name: stepName,
173
+ dependencies
174
+ });
175
+ dependencyGraph.set(stepName, dependencies);
176
+ indegree.set(stepName, dependencies.length);
177
+ }
178
+ // Topological sort to determine execution batches
179
+ const executionBatches = [];
180
+ const processed = new Set();
181
+ while(processed.size < steps.length){
182
+ const currentBatch = [];
183
+ // Find all steps with no remaining dependencies
184
+ for (const [stepName, inDegree] of indegree.entries()){
185
+ if (inDegree === 0 && !processed.has(stepName)) {
186
+ const step = stepMap.get(stepName);
187
+ if (step) {
188
+ currentBatch.push(step);
189
+ }
190
+ }
191
+ }
192
+ if (currentBatch.length === 0) {
193
+ throw new Error('Circular dependency detected in workflow steps');
194
+ }
195
+ executionBatches.push(currentBatch);
196
+ // Update indegrees for next iteration
197
+ for (const step of currentBatch){
198
+ processed.add(step.name);
199
+ // Reduce indegree for steps that depend on completed steps
200
+ for (const [otherStepName, dependencies] of dependencyGraph.entries()){
201
+ if (dependencies.includes(step.name) && !processed.has(otherStepName)) {
202
+ indegree.set(otherStepName, (indegree.get(otherStepName) || 0) - 1);
203
+ }
204
+ }
205
+ }
206
+ }
207
+ return executionBatches;
208
+ }
209
+ /**
210
+ * Resolve step input using JSONPath expressions
211
+ */ resolveStepInput(config, context) {
212
+ const resolved = {};
213
+ for (const [key, value] of Object.entries(config)){
214
+ if (typeof value === 'string' && value.startsWith('$')) {
215
+ // This is a JSONPath expression
216
+ try {
217
+ const result = JSONPath({
218
+ json: context,
219
+ path: value,
220
+ wrap: false
221
+ });
222
+ resolved[key] = result;
223
+ } catch (error) {
224
+ this.logger.warn({
225
+ error: error instanceof Error ? error.message : 'Unknown error',
226
+ key,
227
+ path: value
228
+ }, 'Failed to resolve JSONPath');
229
+ resolved[key] = value; // Keep original value if resolution fails
230
+ }
231
+ } else if (typeof value === 'object' && value !== null) {
232
+ // Recursively resolve nested objects
233
+ resolved[key] = this.resolveStepInput(value, context);
234
+ } else {
235
+ // Keep literal values as-is
236
+ resolved[key] = value;
237
+ }
238
+ }
239
+ return resolved;
240
+ }
241
+ /**
242
+ * Update workflow run with current context
243
+ */ async updateWorkflowRunContext(workflowRunId, context, req) {
244
+ const serializeContext = ()=>({
245
+ steps: context.steps,
246
+ trigger: {
247
+ type: context.trigger.type,
248
+ collection: context.trigger.collection,
249
+ data: context.trigger.data,
250
+ doc: context.trigger.doc,
251
+ operation: context.trigger.operation,
252
+ previousDoc: context.trigger.previousDoc,
253
+ triggeredAt: context.trigger.triggeredAt,
254
+ user: context.trigger.req?.user
255
+ }
256
+ });
257
+ await this.payload.update({
258
+ id: workflowRunId,
259
+ collection: 'workflow-runs',
260
+ data: {
261
+ context: serializeContext()
262
+ },
263
+ req
264
+ });
265
+ }
266
+ /**
267
+ * Evaluate a condition using JSONPath
268
+ */ evaluateCondition(condition, context) {
269
+ try {
270
+ const result = JSONPath({
271
+ json: context,
272
+ path: condition,
273
+ wrap: false
274
+ });
275
+ // Handle different result types
276
+ if (Array.isArray(result)) {
277
+ return result.length > 0 && Boolean(result[0]);
278
+ }
279
+ return Boolean(result);
280
+ } catch (error) {
281
+ this.logger.warn({
282
+ condition,
283
+ error: error instanceof Error ? error.message : 'Unknown error'
284
+ }, 'Failed to evaluate condition');
285
+ // If condition evaluation fails, assume false
286
+ return false;
287
+ }
288
+ }
289
+ /**
290
+ * Execute a workflow with the given context
291
+ */ async execute(workflow, context, req) {
292
+ this.logger.info({
293
+ workflowId: workflow.id,
294
+ workflowName: workflow.name
295
+ }, 'Starting workflow execution');
296
+ const serializeContext = ()=>({
297
+ steps: context.steps,
298
+ trigger: {
299
+ type: context.trigger.type,
300
+ collection: context.trigger.collection,
301
+ data: context.trigger.data,
302
+ doc: context.trigger.doc,
303
+ operation: context.trigger.operation,
304
+ previousDoc: context.trigger.previousDoc,
305
+ triggeredAt: context.trigger.triggeredAt,
306
+ user: context.trigger.req?.user
307
+ }
308
+ });
309
+ // Create a workflow run record
310
+ const workflowRun = await this.payload.create({
311
+ collection: 'workflow-runs',
312
+ data: {
313
+ context: serializeContext(),
314
+ startedAt: new Date().toISOString(),
315
+ status: 'running',
316
+ triggeredBy: context.trigger.req?.user?.email || 'system',
317
+ workflow: workflow.id,
318
+ workflowVersion: workflow._version || 1
319
+ },
320
+ req
321
+ });
322
+ try {
323
+ // Resolve execution order based on dependencies
324
+ const executionBatches = this.resolveExecutionOrder(workflow.steps);
325
+ this.logger.info({
326
+ batchSizes: executionBatches.map((batch)=>batch.length),
327
+ totalBatches: executionBatches.length
328
+ }, 'Resolved step execution order');
329
+ // Execute each batch in sequence, but steps within each batch in parallel
330
+ for(let batchIndex = 0; batchIndex < executionBatches.length; batchIndex++){
331
+ const batch = executionBatches[batchIndex];
332
+ this.logger.info({
333
+ batchIndex,
334
+ stepCount: batch.length,
335
+ stepNames: batch.map((s)=>s.name)
336
+ }, 'Executing batch');
337
+ // Execute all steps in this batch in parallel
338
+ const batchPromises = batch.map((step, stepIndex)=>this.executeStep(step, stepIndex, context, req, workflowRun.id));
339
+ // Wait for all steps in the current batch to complete
340
+ await Promise.all(batchPromises);
341
+ this.logger.info({
342
+ batchIndex,
343
+ stepCount: batch.length
344
+ }, 'Batch completed');
345
+ }
346
+ // Update workflow run as completed
347
+ await this.payload.update({
348
+ id: workflowRun.id,
349
+ collection: 'workflow-runs',
350
+ data: {
351
+ completedAt: new Date().toISOString(),
352
+ context: serializeContext(),
353
+ status: 'completed'
354
+ },
355
+ req
356
+ });
357
+ this.logger.info({
358
+ runId: workflowRun.id,
359
+ workflowId: workflow.id,
360
+ workflowName: workflow.name
361
+ }, 'Workflow execution completed');
362
+ } catch (error) {
363
+ // Update workflow run as failed
364
+ await this.payload.update({
365
+ id: workflowRun.id,
366
+ collection: 'workflow-runs',
367
+ data: {
368
+ completedAt: new Date().toISOString(),
369
+ context: serializeContext(),
370
+ error: error instanceof Error ? error.message : 'Unknown error',
371
+ status: 'failed'
372
+ },
373
+ req
374
+ });
375
+ this.logger.error({
376
+ error: error instanceof Error ? error.message : 'Unknown error',
377
+ runId: workflowRun.id,
378
+ workflowId: workflow.id,
379
+ workflowName: workflow.name
380
+ }, 'Workflow execution failed');
381
+ throw error;
382
+ }
383
+ }
384
+ /**
385
+ * Find and execute workflows triggered by a collection operation
386
+ */ async executeTriggeredWorkflows(collection, operation, doc, previousDoc, req) {
387
+ try {
388
+ // Find workflows with matching triggers
389
+ const workflows = await this.payload.find({
390
+ collection: 'workflows',
391
+ depth: 2,
392
+ limit: 100,
393
+ req
394
+ });
395
+ for (const workflow of workflows.docs){
396
+ // Check if this workflow has a matching trigger
397
+ const triggers = workflow.triggers;
398
+ const matchingTriggers = triggers?.filter((trigger)=>trigger.type === 'collection-trigger' && trigger.collection === collection && trigger.operation === operation) || [];
399
+ for (const trigger of matchingTriggers){
400
+ // Create execution context for condition evaluation
401
+ const context = {
402
+ steps: {},
403
+ trigger: {
404
+ type: 'collection',
405
+ collection,
406
+ doc,
407
+ operation,
408
+ previousDoc,
409
+ req
410
+ }
411
+ };
412
+ // Check trigger condition if present
413
+ if (trigger.condition) {
414
+ const conditionMet = this.evaluateCondition(trigger.condition, context);
415
+ if (!conditionMet) {
416
+ this.logger.info({
417
+ collection,
418
+ condition: trigger.condition,
419
+ operation,
420
+ workflowId: workflow.id,
421
+ workflowName: workflow.name
422
+ }, 'Trigger condition not met, skipping workflow');
423
+ continue;
424
+ }
425
+ this.logger.info({
426
+ collection,
427
+ condition: trigger.condition,
428
+ operation,
429
+ workflowId: workflow.id,
430
+ workflowName: workflow.name
431
+ }, 'Trigger condition met');
432
+ }
433
+ this.logger.info({
434
+ collection,
435
+ operation,
436
+ workflowId: workflow.id,
437
+ workflowName: workflow.name
438
+ }, 'Triggering workflow');
439
+ // Execute the workflow
440
+ await this.execute(workflow, context, req);
441
+ }
442
+ }
443
+ } catch (error) {
444
+ this.logger.error({
445
+ error: error instanceof Error ? error.message : 'Unknown error'
446
+ }, 'Workflow execution failed');
447
+ this.logger.error({
448
+ collection,
449
+ error: error instanceof Error ? error.message : 'Unknown error',
450
+ operation
451
+ }, 'Failed to execute triggered workflows');
452
+ }
453
+ }
454
+ }
455
+
456
+ //# sourceMappingURL=workflow-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/workflow-executor.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\nimport { JSONPath } from 'jsonpath-plus'\n\nexport type Workflow = {\n _version?: number\n id: string\n name: string\n steps: WorkflowStep[]\n triggers: WorkflowTrigger[]\n}\n\nexport type WorkflowStep = {\n condition?: string\n dependencies?: string[]\n input?: null | Record<string, unknown>\n name: string\n step: string\n}\n\nexport interface WorkflowTrigger {\n collection?: string\n condition?: string\n global?: string\n globalOperation?: string\n operation?: string\n type: string\n webhookPath?: string\n}\n\nexport interface ExecutionContext {\n steps: Record<string, {\n error?: string\n input: unknown\n output: unknown\n state: 'failed' | 'pending' | 'running' | 'succeeded'\n }>\n trigger: {\n collection?: string\n data?: unknown\n doc?: unknown\n headers?: Record<string, string>\n operation?: string\n path?: string\n previousDoc?: unknown\n req?: PayloadRequest\n triggeredAt?: string\n type: string\n user?: {\n collection?: string\n email?: string\n id?: string\n }\n }\n}\n\nexport class WorkflowExecutor {\n constructor(\n private payload: Payload,\n private logger: Payload['logger']\n ) {}\n\n /**\n * Evaluate a step condition using JSONPath\n */\n private evaluateStepCondition(condition: string, context: ExecutionContext): boolean {\n return this.evaluateCondition(condition, context)\n }\n\n /**\n * Execute a single workflow step\n */\n private async executeStep(\n step: WorkflowStep,\n stepIndex: number,\n context: ExecutionContext,\n req: PayloadRequest,\n workflowRunId?: number | string\n ): Promise<void> {\n const stepName = step.name || 'step-' + stepIndex\n\n this.logger.info({\n hasStep: 'step' in step,\n step: JSON.stringify(step),\n stepName\n }, 'Executing step')\n\n // Check step condition if present\n if (step.condition) {\n const conditionMet = this.evaluateStepCondition(step.condition, context)\n\n if (!conditionMet) {\n this.logger.info({\n condition: step.condition,\n stepName\n }, 'Step condition not met, skipping')\n\n // Mark step as completed but skipped\n context.steps[stepName] = {\n error: undefined,\n input: undefined,\n output: { reason: 'Condition not met', skipped: true },\n state: 'succeeded'\n }\n\n // Update workflow run context if needed\n if (workflowRunId) {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n }\n\n return\n }\n\n this.logger.info({\n condition: step.condition,\n stepName\n }, 'Step condition met, proceeding with execution')\n }\n\n // Initialize step context\n context.steps[stepName] = {\n error: undefined,\n input: undefined,\n output: undefined,\n state: 'running'\n }\n\n // Move taskSlug declaration outside try block so it's accessible in catch\n const taskSlug = step.step // Use the 'step' field for task type\n\n try {\n // Resolve input data using JSONPath\n const resolvedInput = this.resolveStepInput(step.input || {}, context)\n context.steps[stepName].input = resolvedInput\n\n if (!taskSlug) {\n throw new Error(`Step ${stepName} is missing a task type`)\n }\n\n this.logger.info({\n hasInput: !!resolvedInput,\n hasReq: !!req,\n stepName,\n taskSlug\n }, 'Queueing task')\n\n const job = await this.payload.jobs.queue({\n input: resolvedInput,\n req,\n task: taskSlug\n })\n\n // Run the job immediately\n await this.payload.jobs.run({\n limit: 1,\n req\n })\n\n // Get the job result\n const completedJob = await this.payload.findByID({\n id: job.id,\n collection: 'payload-jobs',\n req\n })\n\n const taskStatus = completedJob.taskStatus?.[completedJob.taskSlug]?.[completedJob.totalTried]\n const isComplete = taskStatus?.complete === true\n const hasError = completedJob.hasError || !isComplete\n\n // Extract error information from job if available\n let errorMessage: string | undefined\n if (hasError) {\n // Try to get error from the latest log entry\n if (completedJob.log && completedJob.log.length > 0) {\n const latestLog = completedJob.log[completedJob.log.length - 1]\n errorMessage = latestLog.error?.message || latestLog.error\n }\n\n // Fallback to top-level error\n if (!errorMessage && completedJob.error) {\n errorMessage = completedJob.error.message || completedJob.error\n }\n\n // Final fallback to generic message\n if (!errorMessage) {\n errorMessage = `Task ${taskSlug} failed without detailed error information`\n }\n }\n\n const result: {\n error: string | undefined\n output: unknown\n state: 'failed' | 'succeeded'\n } = {\n error: errorMessage,\n output: taskStatus?.output || {},\n state: isComplete ? 'succeeded' : 'failed'\n }\n\n // Store the output and error\n context.steps[stepName].output = result.output\n context.steps[stepName].state = result.state\n if (result.error) {\n context.steps[stepName].error = result.error\n }\n\n this.logger.debug({context}, 'Step execution context')\n\n if (result.state !== 'succeeded') {\n throw new Error(result.error || `Step ${stepName} failed`)\n }\n\n this.logger.info({\n output: result.output,\n stepName\n }, 'Step completed')\n\n // Update workflow run with current step results if workflowRunId is provided\n if (workflowRunId) {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n }\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n context.steps[stepName].state = 'failed'\n context.steps[stepName].error = errorMessage\n\n this.logger.error({\n error: errorMessage,\n input: context.steps[stepName].input,\n stepName,\n taskSlug\n }, 'Step execution failed')\n\n // Update workflow run with current step results if workflowRunId is provided\n if (workflowRunId) {\n try {\n await this.updateWorkflowRunContext(workflowRunId, context, req)\n } catch (updateError) {\n this.logger.error({\n error: updateError instanceof Error ? updateError.message : 'Unknown error',\n stepName\n }, 'Failed to update workflow run context after step failure')\n }\n }\n\n throw error\n }\n }\n\n /**\n * Resolve step execution order based on dependencies\n */\n private resolveExecutionOrder(steps: WorkflowStep[]): WorkflowStep[][] {\n const stepMap = new Map<string, WorkflowStep>()\n const dependencyGraph = new Map<string, string[]>()\n const indegree = new Map<string, number>()\n\n // Build the step map and dependency graph\n for (const step of steps) {\n const stepName = step.name || `step-${steps.indexOf(step)}`\n const dependencies = step.dependencies || []\n\n stepMap.set(stepName, { ...step, name: stepName, dependencies })\n dependencyGraph.set(stepName, dependencies)\n indegree.set(stepName, dependencies.length)\n }\n\n // Topological sort to determine execution batches\n const executionBatches: WorkflowStep[][] = []\n const processed = new Set<string>()\n\n while (processed.size < steps.length) {\n const currentBatch: WorkflowStep[] = []\n\n // Find all steps with no remaining dependencies\n for (const [stepName, inDegree] of indegree.entries()) {\n if (inDegree === 0 && !processed.has(stepName)) {\n const step = stepMap.get(stepName)\n if (step) {\n currentBatch.push(step)\n }\n }\n }\n\n if (currentBatch.length === 0) {\n throw new Error('Circular dependency detected in workflow steps')\n }\n\n executionBatches.push(currentBatch)\n\n // Update indegrees for next iteration\n for (const step of currentBatch) {\n processed.add(step.name)\n\n // Reduce indegree for steps that depend on completed steps\n for (const [otherStepName, dependencies] of dependencyGraph.entries()) {\n if (dependencies.includes(step.name) && !processed.has(otherStepName)) {\n indegree.set(otherStepName, (indegree.get(otherStepName) || 0) - 1)\n }\n }\n }\n }\n\n return executionBatches\n }\n\n /**\n * Resolve step input using JSONPath expressions\n */\n private resolveStepInput(config: Record<string, unknown>, context: ExecutionContext): Record<string, unknown> {\n const resolved: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === 'string' && value.startsWith('$')) {\n // This is a JSONPath expression\n try {\n const result = JSONPath({\n json: context,\n path: value,\n wrap: false\n })\n resolved[key] = result\n } catch (error) {\n this.logger.warn({\n error: error instanceof Error ? error.message : 'Unknown error',\n key,\n path: value\n }, 'Failed to resolve JSONPath')\n resolved[key] = value // Keep original value if resolution fails\n }\n } else if (typeof value === 'object' && value !== null) {\n // Recursively resolve nested objects\n resolved[key] = this.resolveStepInput(value as Record<string, unknown>, context)\n } else {\n // Keep literal values as-is\n resolved[key] = value\n }\n }\n\n return resolved\n }\n\n /**\n * Update workflow run with current context\n */\n private async updateWorkflowRunContext(\n workflowRunId: number | string,\n context: ExecutionContext,\n req: PayloadRequest\n ): Promise<void> {\n const serializeContext = () => ({\n steps: context.steps,\n trigger: {\n type: context.trigger.type,\n collection: context.trigger.collection,\n data: context.trigger.data,\n doc: context.trigger.doc,\n operation: context.trigger.operation,\n previousDoc: context.trigger.previousDoc,\n triggeredAt: context.trigger.triggeredAt,\n user: context.trigger.req?.user\n }\n })\n\n await this.payload.update({\n id: workflowRunId,\n collection: 'workflow-runs',\n data: {\n context: serializeContext()\n },\n req\n })\n }\n\n /**\n * Evaluate a condition using JSONPath\n */\n public evaluateCondition(condition: string, context: ExecutionContext): boolean {\n try {\n const result = JSONPath({\n json: context,\n path: condition,\n wrap: false\n })\n\n // Handle different result types\n if (Array.isArray(result)) {\n return result.length > 0 && Boolean(result[0])\n }\n\n return Boolean(result)\n } catch (error) {\n this.logger.warn({\n condition,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to evaluate condition')\n\n // If condition evaluation fails, assume false\n return false\n }\n }\n\n /**\n * Execute a workflow with the given context\n */\n async execute(workflow: Workflow, context: ExecutionContext, req: PayloadRequest): Promise<void> {\n this.logger.info({\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Starting workflow execution')\n\n const serializeContext = () => ({\n steps: context.steps,\n trigger: {\n type: context.trigger.type,\n collection: context.trigger.collection,\n data: context.trigger.data,\n doc: context.trigger.doc,\n operation: context.trigger.operation,\n previousDoc: context.trigger.previousDoc,\n triggeredAt: context.trigger.triggeredAt,\n user: context.trigger.req?.user\n }\n })\n\n // Create a workflow run record\n const workflowRun = await this.payload.create({\n collection: 'workflow-runs',\n data: {\n context: serializeContext(),\n startedAt: new Date().toISOString(),\n status: 'running',\n triggeredBy: context.trigger.req?.user?.email || 'system',\n workflow: workflow.id,\n workflowVersion: workflow._version || 1\n },\n req\n })\n\n try {\n // Resolve execution order based on dependencies\n const executionBatches = this.resolveExecutionOrder(workflow.steps)\n\n this.logger.info({\n batchSizes: executionBatches.map(batch => batch.length),\n totalBatches: executionBatches.length\n }, 'Resolved step execution order')\n\n // Execute each batch in sequence, but steps within each batch in parallel\n for (let batchIndex = 0; batchIndex < executionBatches.length; batchIndex++) {\n const batch = executionBatches[batchIndex]\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length,\n stepNames: batch.map(s => s.name)\n }, 'Executing batch')\n\n // Execute all steps in this batch in parallel\n const batchPromises = batch.map((step, stepIndex) =>\n this.executeStep(step, stepIndex, context, req, workflowRun.id)\n )\n\n // Wait for all steps in the current batch to complete\n await Promise.all(batchPromises)\n\n this.logger.info({\n batchIndex,\n stepCount: batch.length\n }, 'Batch completed')\n }\n\n // Update workflow run as completed\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n completedAt: new Date().toISOString(),\n context: serializeContext(),\n status: 'completed'\n },\n req\n })\n\n this.logger.info({\n runId: workflowRun.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Workflow execution completed')\n\n } catch (error) {\n // Update workflow run as failed\n await this.payload.update({\n id: workflowRun.id,\n collection: 'workflow-runs',\n data: {\n completedAt: new Date().toISOString(),\n context: serializeContext(),\n error: error instanceof Error ? error.message : 'Unknown error',\n status: 'failed'\n },\n req\n })\n\n this.logger.error({\n error: error instanceof Error ? error.message : 'Unknown error',\n runId: workflowRun.id,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Workflow execution failed')\n\n throw error\n }\n }\n\n /**\n * Find and execute workflows triggered by a collection operation\n */\n async executeTriggeredWorkflows(\n collection: string,\n operation: 'create' | 'delete' | 'read' | 'update',\n doc: unknown,\n previousDoc: unknown,\n req: PayloadRequest\n ): Promise<void> {\n try {\n // Find workflows with matching triggers\n const workflows = await this.payload.find({\n collection: 'workflows',\n depth: 2, // Include steps and triggers\n limit: 100,\n req\n })\n\n for (const workflow of workflows.docs) {\n // Check if this workflow has a matching trigger\n const triggers = workflow.triggers as Array<{\n collection: string\n condition?: string\n operation: string\n type: string\n }>\n\n const matchingTriggers = triggers?.filter(trigger =>\n trigger.type === 'collection-trigger' &&\n trigger.collection === collection &&\n trigger.operation === operation\n ) || []\n\n for (const trigger of matchingTriggers) {\n // Create execution context for condition evaluation\n const context: ExecutionContext = {\n steps: {},\n trigger: {\n type: 'collection',\n collection,\n doc,\n operation,\n previousDoc,\n req\n }\n }\n\n // Check trigger condition if present\n if (trigger.condition) {\n const conditionMet = this.evaluateCondition(trigger.condition, context)\n\n if (!conditionMet) {\n this.logger.info({\n collection,\n condition: trigger.condition,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Trigger condition not met, skipping workflow')\n continue\n }\n\n this.logger.info({\n collection,\n condition: trigger.condition,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Trigger condition met')\n }\n\n this.logger.info({\n collection,\n operation,\n workflowId: workflow.id,\n workflowName: workflow.name\n }, 'Triggering workflow')\n\n // Execute the workflow\n await this.execute(workflow as Workflow, context, req)\n }\n }\n } catch (error) {\n this.logger.error({ error: error instanceof Error ? error.message : 'Unknown error' }, 'Workflow execution failed')\n this.logger.error({\n collection,\n error: error instanceof Error ? error.message : 'Unknown error',\n operation\n }, 'Failed to execute triggered workflows')\n }\n }\n}\n"],"names":["JSONPath","WorkflowExecutor","payload","logger","evaluateStepCondition","condition","context","evaluateCondition","executeStep","step","stepIndex","req","workflowRunId","stepName","name","info","hasStep","JSON","stringify","conditionMet","steps","error","undefined","input","output","reason","skipped","state","updateWorkflowRunContext","taskSlug","resolvedInput","resolveStepInput","Error","hasInput","hasReq","job","jobs","queue","task","run","limit","completedJob","findByID","id","collection","taskStatus","totalTried","isComplete","complete","hasError","errorMessage","log","length","latestLog","message","result","debug","updateError","resolveExecutionOrder","stepMap","Map","dependencyGraph","indegree","indexOf","dependencies","set","executionBatches","processed","Set","size","currentBatch","inDegree","entries","has","get","push","add","otherStepName","includes","config","resolved","key","value","Object","startsWith","json","path","wrap","warn","serializeContext","trigger","type","data","doc","operation","previousDoc","triggeredAt","user","update","Array","isArray","Boolean","execute","workflow","workflowId","workflowName","workflowRun","create","startedAt","Date","toISOString","status","triggeredBy","email","workflowVersion","_version","batchSizes","map","batch","totalBatches","batchIndex","stepCount","stepNames","s","batchPromises","Promise","all","completedAt","runId","executeTriggeredWorkflows","workflows","find","depth","docs","triggers","matchingTriggers","filter"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { TriggerWorkflowButton } from '../components/TriggerWorkflowButton.js';
@@ -0,0 +1,7 @@
1
+ // Client-side components that may have CSS imports or PayloadCMS UI dependencies
2
+ // These are separated to avoid CSS import errors during Node.js type generation
3
+ export { TriggerWorkflowButton } from '../components/TriggerWorkflowButton.js'; // Future client components can be added here:
4
+ // export { default as WorkflowDashboard } from '../components/WorkflowDashboard/index.js'
5
+ // export { default as WorkflowBuilder } from '../components/WorkflowBuilder/index.js'
6
+
7
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["// Client-side components that may have CSS imports or PayloadCMS UI dependencies\n// These are separated to avoid CSS import errors during Node.js type generation\n\nexport { TriggerWorkflowButton } from '../components/TriggerWorkflowButton.js'\n\n// Future client components can be added here:\n// export { default as WorkflowDashboard } from '../components/WorkflowDashboard/index.js'\n// export { default as WorkflowBuilder } from '../components/WorkflowBuilder/index.js'\n"],"names":["TriggerWorkflowButton"],"mappings":"AAAA,iFAAiF;AACjF,gFAAgF;AAEhF,SAASA,qBAAqB,QAAQ,yCAAwC,CAE9E,8CAA8C;CAC9C,0FAA0F;CAC1F,sFAAsF"}
@@ -0,0 +1 @@
1
+ export declare const WorkflowFields: {};
@@ -0,0 +1,6 @@
1
+ // Field exports for workflow plugin
2
+ // Currently no custom fields, but this export exists for future extensibility
3
+ export const WorkflowFields = {
4
+ };
5
+
6
+ //# sourceMappingURL=fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/fields.ts"],"sourcesContent":["// Field exports for workflow plugin\n// Currently no custom fields, but this export exists for future extensibility\nexport const WorkflowFields = {\n // Custom workflow fields can be added here in the future\n}"],"names":["WorkflowFields"],"mappings":"AAAA,oCAAoC;AACpC,8EAA8E;AAC9E,OAAO,MAAMA,iBAAiB;AAE9B,EAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ // Server-side exports for workflow plugin
2
+
3
+ //# sourceMappingURL=rsc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["// Server-side exports for workflow plugin\n"],"names":[],"mappings":"AAAA,0CAA0C"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ // View exports for workflow plugin
2
+ // Currently no custom views, but this export exists for future extensibility
3
+ // export { default as WorkflowDashboard } from '../components/WorkflowDashboard/index.js'
4
+ // export { default as WorkflowBuilder } from '../components/WorkflowBuilder/index.js'
5
+ // export { default as WorkflowStepsField } from '../components/WorkflowStepsField/index.js'
6
+
7
+ //# sourceMappingURL=views.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/views.ts"],"sourcesContent":["// View exports for workflow plugin\n// Currently no custom views, but this export exists for future extensibility\n\n// export { default as WorkflowDashboard } from '../components/WorkflowDashboard/index.js'\n// export { default as WorkflowBuilder } from '../components/WorkflowBuilder/index.js'\n// export { default as WorkflowStepsField } from '../components/WorkflowStepsField/index.js'\n"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,6EAA6E;AAE7E,0FAA0F;AAC1F,sFAAsF;AACtF,4FAA4F"}
@@ -0,0 +1,7 @@
1
+ export { triggerCustomWorkflow, triggerWorkflowById } from './core/trigger-custom-workflow.js';
2
+ export type { CustomTriggerOptions, TriggerResult } from './core/trigger-custom-workflow.js';
3
+ export { WorkflowExecutor } from './core/workflow-executor.js';
4
+ export type { ExecutionContext, Workflow, WorkflowStep, WorkflowTrigger } from './core/workflow-executor.js';
5
+ export type { WorkflowsPluginConfig } from './plugin/config-types.js';
6
+ export { workflowsPlugin } from './plugin/index.js';
7
+ export { CreateDocumentStepTask, DeleteDocumentStepTask, HttpRequestStepTask, ReadDocumentStepTask, SendEmailStepTask, UpdateDocumentStepTask } from './steps/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { triggerCustomWorkflow, triggerWorkflowById } from './core/trigger-custom-workflow.js';
2
+ export { WorkflowExecutor } from './core/workflow-executor.js';
3
+ export { workflowsPlugin } from './plugin/index.js';
4
+ // Export all step tasks
5
+ export { CreateDocumentStepTask, DeleteDocumentStepTask, HttpRequestStepTask, ReadDocumentStepTask, SendEmailStepTask, UpdateDocumentStepTask } from './steps/index.js'; // UI components are exported via separate client export to avoid CSS import issues during type generation
6
+ // Use: import { TriggerWorkflowButton } from '@xtr-dev/payload-automation/client'
7
+
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { triggerCustomWorkflow, triggerWorkflowById } from './core/trigger-custom-workflow.js'\nexport type { CustomTriggerOptions, TriggerResult } from './core/trigger-custom-workflow.js'\nexport { WorkflowExecutor } from './core/workflow-executor.js'\nexport type { ExecutionContext, Workflow, WorkflowStep, WorkflowTrigger } from './core/workflow-executor.js'\nexport type { WorkflowsPluginConfig } from './plugin/config-types.js'\nexport { workflowsPlugin } from './plugin/index.js'\n\n// Export all step tasks\nexport {\n CreateDocumentStepTask,\n DeleteDocumentStepTask,\n HttpRequestStepTask,\n ReadDocumentStepTask,\n SendEmailStepTask,\n UpdateDocumentStepTask\n} from './steps/index.js'\n\n// UI components are exported via separate client export to avoid CSS import issues during type generation\n// Use: import { TriggerWorkflowButton } from '@xtr-dev/payload-automation/client'\n"],"names":["triggerCustomWorkflow","triggerWorkflowById","WorkflowExecutor","workflowsPlugin","CreateDocumentStepTask","DeleteDocumentStepTask","HttpRequestStepTask","ReadDocumentStepTask","SendEmailStepTask","UpdateDocumentStepTask"],"mappings":"AAAA,SAASA,qBAAqB,EAAEC,mBAAmB,QAAQ,oCAAmC;AAE9F,SAASC,gBAAgB,QAAQ,8BAA6B;AAG9D,SAASC,eAAe,QAAQ,oBAAmB;AAEnD,wBAAwB;AACxB,SACEC,sBAAsB,EACtBC,sBAAsB,EACtBC,mBAAmB,EACnBC,oBAAoB,EACpBC,iBAAiB,EACjBC,sBAAsB,QACjB,mBAAkB,CAEzB,0GAA0G;CAC1G,kFAAkF"}
@@ -0,0 +1,21 @@
1
+ import type { Field, TaskConfig } from "payload";
2
+ export type CollectionTriggerConfigCrud = {
3
+ create?: true;
4
+ delete?: true;
5
+ read?: true;
6
+ update?: true;
7
+ };
8
+ export type CollectionTriggerConfig = CollectionTriggerConfigCrud | true;
9
+ export type CustomTriggerConfig = {
10
+ inputs?: Field[];
11
+ slug: string;
12
+ };
13
+ export type WorkflowsPluginConfig<TSlug extends string> = {
14
+ collectionTriggers: {
15
+ [key in TSlug]?: CollectionTriggerConfig;
16
+ };
17
+ enabled?: boolean;
18
+ steps: TaskConfig<string>[];
19
+ triggers?: CustomTriggerConfig[];
20
+ webhookPrefix?: string;
21
+ };
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=config-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugin/config-types.ts"],"sourcesContent":["import type {Field, TaskConfig} from \"payload\"\n\nexport type CollectionTriggerConfigCrud = {\n create?: true\n delete?: true\n read?: true\n update?: true\n}\n\nexport type CollectionTriggerConfig = CollectionTriggerConfigCrud | true\n\nexport type CustomTriggerConfig = {\n inputs?: Field[]\n slug: string,\n}\n\nexport type WorkflowsPluginConfig<TSlug extends string> = {\n collectionTriggers: {\n [key in TSlug]?: CollectionTriggerConfig\n }\n enabled?: boolean\n steps: TaskConfig<string>[],\n triggers?: CustomTriggerConfig[]\n webhookPrefix?: string\n}\n"],"names":[],"mappings":"AAgBA,WAQC"}