@xtr-dev/payload-automation 0.0.38 → 0.0.39
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 +6 -1
- package/dist/collections/Workflow.js +2 -4
- package/dist/collections/Workflow.js.map +1 -1
- package/dist/components/WorkflowBuilder/StepConfigurationForm.js +316 -0
- package/dist/components/WorkflowBuilder/StepConfigurationForm.js.map +1 -0
- package/dist/components/WorkflowBuilder/WorkflowBuilder.js +211 -0
- package/dist/components/WorkflowBuilder/WorkflowBuilder.js.map +1 -0
- package/dist/components/WorkflowBuilder/WorkflowToolbar.js +107 -0
- package/dist/components/WorkflowBuilder/WorkflowToolbar.js.map +1 -0
- package/dist/components/WorkflowBuilder/index.js +6 -0
- package/dist/components/WorkflowBuilder/index.js.map +1 -0
- package/dist/components/WorkflowBuilder/nodes/StepNode.js +139 -0
- package/dist/components/WorkflowBuilder/nodes/StepNode.js.map +1 -0
- package/dist/core/workflow-executor.js +150 -116
- package/dist/core/workflow-executor.js.map +1 -1
- package/dist/fields/WorkflowBuilderField.js +119 -0
- package/dist/fields/WorkflowBuilderField.js.map +1 -0
- package/dist/plugin/collection-hook.js +34 -0
- package/dist/plugin/collection-hook.js.map +1 -1
- package/package.json +4 -3
- package/dist/collections/Workflow.d.ts +0 -3
- package/dist/collections/WorkflowRuns.d.ts +0 -2
- package/dist/components/ErrorDisplay.d.ts +0 -9
- package/dist/components/StatusCell.d.ts +0 -6
- package/dist/core/trigger-custom-workflow.d.ts +0 -52
- package/dist/core/workflow-executor.d.ts +0 -90
- package/dist/exports/client.d.ts +0 -2
- package/dist/exports/fields.d.ts +0 -1
- package/dist/exports/rsc.d.ts +0 -1
- package/dist/exports/server.d.ts +0 -5
- package/dist/exports/views.d.ts +0 -1
- package/dist/fields/parameter.d.ts +0 -4
- package/dist/index.d.ts +0 -2
- package/dist/plugin/collection-hook.d.ts +0 -1
- package/dist/plugin/config-types.d.ts +0 -18
- package/dist/plugin/global-hook.d.ts +0 -1
- package/dist/plugin/index.d.ts +0 -4
- package/dist/plugin/logger.d.ts +0 -20
- package/dist/steps/create-document-handler.d.ts +0 -2
- package/dist/steps/create-document.d.ts +0 -46
- package/dist/steps/delete-document-handler.d.ts +0 -2
- package/dist/steps/delete-document.d.ts +0 -39
- package/dist/steps/http-request-handler.d.ts +0 -2
- package/dist/steps/http-request.d.ts +0 -155
- package/dist/steps/index.d.ts +0 -12
- package/dist/steps/read-document-handler.d.ts +0 -2
- package/dist/steps/read-document.d.ts +0 -46
- package/dist/steps/send-email-handler.d.ts +0 -2
- package/dist/steps/send-email.d.ts +0 -44
- package/dist/steps/update-document-handler.d.ts +0 -2
- package/dist/steps/update-document.d.ts +0 -46
- package/dist/test/basic.test.js +0 -14
- package/dist/test/basic.test.js.map +0 -1
- package/dist/test/create-document-step.test.js +0 -378
- package/dist/test/create-document-step.test.js.map +0 -1
- package/dist/test/http-request-step.test.js +0 -361
- package/dist/test/http-request-step.test.js.map +0 -1
- package/dist/test/workflow-executor.test.js +0 -530
- package/dist/test/workflow-executor.test.js.map +0 -1
- package/dist/triggers/collection-trigger.d.ts +0 -2
- package/dist/triggers/global-trigger.d.ts +0 -2
- package/dist/triggers/index.d.ts +0 -2
- package/dist/triggers/types.d.ts +0 -5
- package/dist/types/index.d.ts +0 -31
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
4
|
+
import { useField } from '@payloadcms/ui';
|
|
5
|
+
import { WorkflowBuilder } from '../components/WorkflowBuilder/index.js';
|
|
6
|
+
// Import the step types from the steps module
|
|
7
|
+
import * as stepTasks from '../steps/index.js';
|
|
8
|
+
// Extract available step types from imported tasks
|
|
9
|
+
const getAvailableStepTypes = ()=>{
|
|
10
|
+
const stepTypes = [];
|
|
11
|
+
// Get all exported step tasks
|
|
12
|
+
const tasks = [
|
|
13
|
+
stepTasks.HttpRequestStepTask,
|
|
14
|
+
stepTasks.CreateDocumentStepTask,
|
|
15
|
+
stepTasks.ReadDocumentStepTask,
|
|
16
|
+
stepTasks.UpdateDocumentStepTask,
|
|
17
|
+
stepTasks.DeleteDocumentStepTask,
|
|
18
|
+
stepTasks.SendEmailStepTask
|
|
19
|
+
];
|
|
20
|
+
tasks.forEach((task)=>{
|
|
21
|
+
if (task && task.slug) {
|
|
22
|
+
stepTypes.push({
|
|
23
|
+
slug: task.slug,
|
|
24
|
+
label: undefined,
|
|
25
|
+
inputSchema: task.inputSchema,
|
|
26
|
+
outputSchema: task.outputSchema
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return stepTypes;
|
|
31
|
+
};
|
|
32
|
+
export const WorkflowBuilderField = ({ name, path })=>{
|
|
33
|
+
const availableStepTypes = getAvailableStepTypes();
|
|
34
|
+
const { value: steps, setValue: setSteps } = useField({
|
|
35
|
+
path: 'steps'
|
|
36
|
+
});
|
|
37
|
+
const { value: layout, setValue: setLayout } = useField({
|
|
38
|
+
path: 'layout'
|
|
39
|
+
});
|
|
40
|
+
const { value: workflowName } = useField({
|
|
41
|
+
path: 'name'
|
|
42
|
+
});
|
|
43
|
+
const [workflowData, setWorkflowData] = useState({
|
|
44
|
+
id: 'temp',
|
|
45
|
+
name: workflowName || 'Workflow',
|
|
46
|
+
steps: steps || [],
|
|
47
|
+
layout: layout || {}
|
|
48
|
+
});
|
|
49
|
+
// Update local state when form fields change
|
|
50
|
+
useEffect(()=>{
|
|
51
|
+
setWorkflowData({
|
|
52
|
+
id: 'temp',
|
|
53
|
+
name: workflowName || 'Workflow',
|
|
54
|
+
steps: steps || [],
|
|
55
|
+
layout: layout || {}
|
|
56
|
+
});
|
|
57
|
+
}, [
|
|
58
|
+
steps,
|
|
59
|
+
layout,
|
|
60
|
+
workflowName
|
|
61
|
+
]);
|
|
62
|
+
const handleSave = useCallback((updatedWorkflow)=>{
|
|
63
|
+
// Update the form fields
|
|
64
|
+
if (updatedWorkflow.steps) {
|
|
65
|
+
setSteps(updatedWorkflow.steps);
|
|
66
|
+
}
|
|
67
|
+
if (updatedWorkflow.layout) {
|
|
68
|
+
setLayout(updatedWorkflow.layout);
|
|
69
|
+
}
|
|
70
|
+
}, [
|
|
71
|
+
setSteps,
|
|
72
|
+
setLayout
|
|
73
|
+
]);
|
|
74
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
75
|
+
style: {
|
|
76
|
+
marginTop: '20px',
|
|
77
|
+
marginBottom: '20px',
|
|
78
|
+
border: '1px solid var(--theme-elevation-100)',
|
|
79
|
+
borderRadius: '4px',
|
|
80
|
+
overflow: 'hidden'
|
|
81
|
+
},
|
|
82
|
+
children: [
|
|
83
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
84
|
+
style: {
|
|
85
|
+
background: 'var(--theme-elevation-50)',
|
|
86
|
+
padding: '12px 16px',
|
|
87
|
+
borderBottom: '1px solid var(--theme-elevation-100)'
|
|
88
|
+
},
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ _jsx("h3", {
|
|
91
|
+
style: {
|
|
92
|
+
margin: 0,
|
|
93
|
+
fontSize: '16px',
|
|
94
|
+
fontWeight: '600',
|
|
95
|
+
color: 'var(--theme-text)'
|
|
96
|
+
},
|
|
97
|
+
children: "Visual Workflow Builder"
|
|
98
|
+
}),
|
|
99
|
+
/*#__PURE__*/ _jsx("p", {
|
|
100
|
+
style: {
|
|
101
|
+
margin: '4px 0 0',
|
|
102
|
+
fontSize: '12px',
|
|
103
|
+
color: 'var(--theme-text-400)'
|
|
104
|
+
},
|
|
105
|
+
children: "Drag and drop steps to build your workflow visually. Click on any step to configure its parameters."
|
|
106
|
+
})
|
|
107
|
+
]
|
|
108
|
+
}),
|
|
109
|
+
/*#__PURE__*/ _jsx(WorkflowBuilder, {
|
|
110
|
+
workflow: workflowData,
|
|
111
|
+
availableStepTypes: availableStepTypes,
|
|
112
|
+
onSave: handleSave,
|
|
113
|
+
readonly: false
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
//# sourceMappingURL=WorkflowBuilderField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/fields/WorkflowBuilderField.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useEffect, useState } from 'react'\nimport { useField, useFormFields } from '@payloadcms/ui'\nimport { WorkflowBuilder } from '../components/WorkflowBuilder/index.js'\n\n// Import the step types from the steps module\nimport * as stepTasks from '../steps/index.js'\n\n// Extract available step types from imported tasks\nconst getAvailableStepTypes = () => {\n const stepTypes: Array<{\n slug: string\n label?: string\n inputSchema?: any[]\n outputSchema?: any[]\n }> = []\n\n // Get all exported step tasks\n const tasks = [\n stepTasks.HttpRequestStepTask,\n stepTasks.CreateDocumentStepTask,\n stepTasks.ReadDocumentStepTask,\n stepTasks.UpdateDocumentStepTask,\n stepTasks.DeleteDocumentStepTask,\n stepTasks.SendEmailStepTask\n ]\n\n tasks.forEach(task => {\n if (task && task.slug) {\n stepTypes.push({\n slug: task.slug,\n label: undefined, // Tasks don't have labels, will use slug\n inputSchema: task.inputSchema,\n outputSchema: task.outputSchema\n })\n }\n })\n\n return stepTypes\n}\n\ninterface WorkflowBuilderFieldProps {\n name?: string\n path?: string\n}\n\nexport const WorkflowBuilderField: React.FC<WorkflowBuilderFieldProps> = ({ \n name, \n path\n}) => {\n const availableStepTypes = getAvailableStepTypes()\n const { value: steps, setValue: setSteps } = useField<any>({ path: 'steps' })\n const { value: layout, setValue: setLayout } = useField<any>({ path: 'layout' })\n const { value: workflowName } = useField<string>({ path: 'name' })\n \n const [workflowData, setWorkflowData] = useState<any>({\n id: 'temp',\n name: workflowName || 'Workflow',\n steps: steps || [],\n layout: layout || {}\n })\n\n // Update local state when form fields change\n useEffect(() => {\n setWorkflowData({\n id: 'temp',\n name: workflowName || 'Workflow',\n steps: steps || [],\n layout: layout || {}\n })\n }, [steps, layout, workflowName])\n\n const handleSave = useCallback((updatedWorkflow: any) => {\n // Update the form fields\n if (updatedWorkflow.steps) {\n setSteps(updatedWorkflow.steps)\n }\n if (updatedWorkflow.layout) {\n setLayout(updatedWorkflow.layout)\n }\n }, [setSteps, setLayout])\n\n return (\n <div style={{ \n marginTop: '20px',\n marginBottom: '20px',\n border: '1px solid var(--theme-elevation-100)',\n borderRadius: '4px',\n overflow: 'hidden'\n }}>\n <div style={{\n background: 'var(--theme-elevation-50)',\n padding: '12px 16px',\n borderBottom: '1px solid var(--theme-elevation-100)'\n }}>\n <h3 style={{ margin: 0, fontSize: '16px', fontWeight: '600', color: 'var(--theme-text)' }}>\n Visual Workflow Builder\n </h3>\n <p style={{ margin: '4px 0 0', fontSize: '12px', color: 'var(--theme-text-400)' }}>\n Drag and drop steps to build your workflow visually. Click on any step to configure its parameters.\n </p>\n </div>\n \n <WorkflowBuilder\n workflow={workflowData}\n availableStepTypes={availableStepTypes}\n onSave={handleSave}\n readonly={false}\n />\n </div>\n )\n}"],"names":["React","useCallback","useEffect","useState","useField","WorkflowBuilder","stepTasks","getAvailableStepTypes","stepTypes","tasks","HttpRequestStepTask","CreateDocumentStepTask","ReadDocumentStepTask","UpdateDocumentStepTask","DeleteDocumentStepTask","SendEmailStepTask","forEach","task","slug","push","label","undefined","inputSchema","outputSchema","WorkflowBuilderField","name","path","availableStepTypes","value","steps","setValue","setSteps","layout","setLayout","workflowName","workflowData","setWorkflowData","id","handleSave","updatedWorkflow","div","style","marginTop","marginBottom","border","borderRadius","overflow","background","padding","borderBottom","h3","margin","fontSize","fontWeight","color","p","workflow","onSave","readonly"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAC/D,SAASC,QAAQ,QAAuB,iBAAgB;AACxD,SAASC,eAAe,QAAQ,yCAAwC;AAExE,8CAA8C;AAC9C,YAAYC,eAAe,oBAAmB;AAE9C,mDAAmD;AACnD,MAAMC,wBAAwB;IAC5B,MAAMC,YAKD,EAAE;IAEP,8BAA8B;IAC9B,MAAMC,QAAQ;QACZH,UAAUI,mBAAmB;QAC7BJ,UAAUK,sBAAsB;QAChCL,UAAUM,oBAAoB;QAC9BN,UAAUO,sBAAsB;QAChCP,UAAUQ,sBAAsB;QAChCR,UAAUS,iBAAiB;KAC5B;IAEDN,MAAMO,OAAO,CAACC,CAAAA;QACZ,IAAIA,QAAQA,KAAKC,IAAI,EAAE;YACrBV,UAAUW,IAAI,CAAC;gBACbD,MAAMD,KAAKC,IAAI;gBACfE,OAAOC;gBACPC,aAAaL,KAAKK,WAAW;gBAC7BC,cAAcN,KAAKM,YAAY;YACjC;QACF;IACF;IAEA,OAAOf;AACT;AAOA,OAAO,MAAMgB,uBAA4D,CAAC,EACxEC,IAAI,EACJC,IAAI,EACL;IACC,MAAMC,qBAAqBpB;IAC3B,MAAM,EAAEqB,OAAOC,KAAK,EAAEC,UAAUC,QAAQ,EAAE,GAAG3B,SAAc;QAAEsB,MAAM;IAAQ;IAC3E,MAAM,EAAEE,OAAOI,MAAM,EAAEF,UAAUG,SAAS,EAAE,GAAG7B,SAAc;QAAEsB,MAAM;IAAS;IAC9E,MAAM,EAAEE,OAAOM,YAAY,EAAE,GAAG9B,SAAiB;QAAEsB,MAAM;IAAO;IAEhE,MAAM,CAACS,cAAcC,gBAAgB,GAAGjC,SAAc;QACpDkC,IAAI;QACJZ,MAAMS,gBAAgB;QACtBL,OAAOA,SAAS,EAAE;QAClBG,QAAQA,UAAU,CAAC;IACrB;IAEA,6CAA6C;IAC7C9B,UAAU;QACRkC,gBAAgB;YACdC,IAAI;YACJZ,MAAMS,gBAAgB;YACtBL,OAAOA,SAAS,EAAE;YAClBG,QAAQA,UAAU,CAAC;QACrB;IACF,GAAG;QAACH;QAAOG;QAAQE;KAAa;IAEhC,MAAMI,aAAarC,YAAY,CAACsC;QAC9B,yBAAyB;QACzB,IAAIA,gBAAgBV,KAAK,EAAE;YACzBE,SAASQ,gBAAgBV,KAAK;QAChC;QACA,IAAIU,gBAAgBP,MAAM,EAAE;YAC1BC,UAAUM,gBAAgBP,MAAM;QAClC;IACF,GAAG;QAACD;QAAUE;KAAU;IAExB,qBACE,MAACO;QAAIC,OAAO;YACVC,WAAW;YACXC,cAAc;YACdC,QAAQ;YACRC,cAAc;YACdC,UAAU;QACZ;;0BACE,MAACN;gBAAIC,OAAO;oBACVM,YAAY;oBACZC,SAAS;oBACTC,cAAc;gBAChB;;kCACE,KAACC;wBAAGT,OAAO;4BAAEU,QAAQ;4BAAGC,UAAU;4BAAQC,YAAY;4BAAOC,OAAO;wBAAoB;kCAAG;;kCAG3F,KAACC;wBAAEd,OAAO;4BAAEU,QAAQ;4BAAWC,UAAU;4BAAQE,OAAO;wBAAwB;kCAAG;;;;0BAKrF,KAACjD;gBACCmD,UAAUrB;gBACVR,oBAAoBA;gBACpB8B,QAAQnB;gBACRoB,UAAU;;;;AAIlB,EAAC"}
|
|
@@ -34,6 +34,40 @@ export const createCollectionTriggerHook = (collectionSlug, hookType)=>{
|
|
|
34
34
|
collection: collectionSlug
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
+
// Check if any trigger has a condition and evaluate it
|
|
38
|
+
let shouldExecute = false;
|
|
39
|
+
for (const trigger of workflow.triggers || []){
|
|
40
|
+
if (trigger.type === 'collection-hook' && trigger.parameters?.collectionSlug === collectionSlug && trigger.parameters?.hook === hookType) {
|
|
41
|
+
if (trigger.condition) {
|
|
42
|
+
// Evaluate the condition
|
|
43
|
+
try {
|
|
44
|
+
const conditionMet = executor.evaluateCondition(trigger.condition, context);
|
|
45
|
+
if (conditionMet) {
|
|
46
|
+
shouldExecute = true;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
payload.logger.error({
|
|
51
|
+
workflowId: workflow.id,
|
|
52
|
+
condition: trigger.condition,
|
|
53
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
54
|
+
}, 'Failed to evaluate trigger condition');
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
// No condition means always execute
|
|
58
|
+
shouldExecute = true;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!shouldExecute) {
|
|
64
|
+
payload.logger.debug({
|
|
65
|
+
workflowId: workflow.id,
|
|
66
|
+
collection: collectionSlug,
|
|
67
|
+
hookType
|
|
68
|
+
}, 'Workflow skipped due to unmet condition');
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
37
71
|
try {
|
|
38
72
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
73
|
await executor.execute(workflow, context, req);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugin/collection-hook.ts"],"sourcesContent":["import {WorkflowExecutor} from \"../core/workflow-executor.js\"\n\nexport const createCollectionTriggerHook = (collectionSlug: string, hookType: string) => {\n return async (args: any) => {\n const req = 'req' in args ? args.req :\n 'args' in args ? args.args.req :\n undefined\n if (!req) {\n throw new Error('No request object found in hook arguments')\n }\n const payload = req.payload\n const {docs: workflows} = await payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n where: {\n 'triggers.parameters.collectionSlug': {\n equals: collectionSlug\n },\n 'triggers.parameters.hook': {\n equals: hookType\n },\n 'triggers.type': {\n equals: 'collection-hook'\n }\n }\n })\n const executor = new WorkflowExecutor(payload, payload.logger)\n // invoke each workflow\n for (const workflow of workflows) {\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n ...args,\n type: 'collection',\n collection: collectionSlug,\n }\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await executor.execute(workflow as any, context, req)\n payload.logger.info({\n workflowId: workflow.id,\n collection: collectionSlug,\n hookType\n }, 'Workflow executed successfully')\n } catch (error) {\n payload.logger.error({\n workflowId: workflow.id,\n collection: collectionSlug,\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}\n"],"names":["WorkflowExecutor","createCollectionTriggerHook","collectionSlug","hookType","args","req","undefined","Error","payload","docs","workflows","find","collection","depth","limit","where","equals","executor","logger","workflow","context","steps","trigger","type","
|
|
1
|
+
{"version":3,"sources":["../../src/plugin/collection-hook.ts"],"sourcesContent":["import {WorkflowExecutor} from \"../core/workflow-executor.js\"\n\nexport const createCollectionTriggerHook = (collectionSlug: string, hookType: string) => {\n return async (args: any) => {\n const req = 'req' in args ? args.req :\n 'args' in args ? args.args.req :\n undefined\n if (!req) {\n throw new Error('No request object found in hook arguments')\n }\n const payload = req.payload\n const {docs: workflows} = await payload.find({\n collection: 'workflows',\n depth: 2,\n limit: 100,\n where: {\n 'triggers.parameters.collectionSlug': {\n equals: collectionSlug\n },\n 'triggers.parameters.hook': {\n equals: hookType\n },\n 'triggers.type': {\n equals: 'collection-hook'\n }\n }\n })\n const executor = new WorkflowExecutor(payload, payload.logger)\n // invoke each workflow\n for (const workflow of workflows) {\n // Create execution context\n const context = {\n steps: {},\n trigger: {\n ...args,\n type: 'collection',\n collection: collectionSlug,\n }\n }\n\n // Check if any trigger has a condition and evaluate it\n let shouldExecute = false\n for (const trigger of workflow.triggers || []) {\n if (trigger.type === 'collection-hook' && \n trigger.parameters?.collectionSlug === collectionSlug && \n trigger.parameters?.hook === hookType) {\n \n if (trigger.condition) {\n // Evaluate the condition\n try {\n const conditionMet = executor.evaluateCondition(trigger.condition, context)\n if (conditionMet) {\n shouldExecute = true\n break\n }\n } catch (error) {\n payload.logger.error({\n workflowId: workflow.id,\n condition: trigger.condition,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 'Failed to evaluate trigger condition')\n }\n } else {\n // No condition means always execute\n shouldExecute = true\n break\n }\n }\n }\n\n if (!shouldExecute) {\n payload.logger.debug({\n workflowId: workflow.id,\n collection: collectionSlug,\n hookType\n }, 'Workflow skipped due to unmet condition')\n continue\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await executor.execute(workflow as any, context, req)\n payload.logger.info({\n workflowId: workflow.id,\n collection: collectionSlug,\n hookType\n }, 'Workflow executed successfully')\n } catch (error) {\n payload.logger.error({\n workflowId: workflow.id,\n collection: collectionSlug,\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}\n"],"names":["WorkflowExecutor","createCollectionTriggerHook","collectionSlug","hookType","args","req","undefined","Error","payload","docs","workflows","find","collection","depth","limit","where","equals","executor","logger","workflow","context","steps","trigger","type","shouldExecute","triggers","parameters","hook","condition","conditionMet","evaluateCondition","error","workflowId","id","message","debug","execute","info"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,+BAA8B;AAE7D,OAAO,MAAMC,8BAA8B,CAACC,gBAAwBC;IAClE,OAAO,OAAOC;QACZ,MAAMC,MAAM,SAASD,OAAOA,KAAKC,GAAG,GAClC,UAAUD,OAAOA,KAAKA,IAAI,CAACC,GAAG,GAC5BC;QACJ,IAAI,CAACD,KAAK;YACR,MAAM,IAAIE,MAAM;QAClB;QACA,MAAMC,UAAUH,IAAIG,OAAO;QAC3B,MAAM,EAACC,MAAMC,SAAS,EAAC,GAAG,MAAMF,QAAQG,IAAI,CAAC;YAC3CC,YAAY;YACZC,OAAO;YACPC,OAAO;YACPC,OAAO;gBACL,sCAAsC;oBACpCC,QAAQd;gBACV;gBACA,4BAA4B;oBAC1Bc,QAAQb;gBACV;gBACA,iBAAiB;oBACfa,QAAQ;gBACV;YACF;QACF;QACA,MAAMC,WAAW,IAAIjB,iBAAiBQ,SAASA,QAAQU,MAAM;QAC7D,uBAAuB;QACvB,KAAK,MAAMC,YAAYT,UAAW;YAChC,2BAA2B;YAC3B,MAAMU,UAAU;gBACdC,OAAO,CAAC;gBACRC,SAAS;oBACP,GAAGlB,IAAI;oBACPmB,MAAM;oBACNX,YAAYV;gBACd;YACF;YAEA,uDAAuD;YACvD,IAAIsB,gBAAgB;YACpB,KAAK,MAAMF,WAAWH,SAASM,QAAQ,IAAI,EAAE,CAAE;gBAC7C,IAAIH,QAAQC,IAAI,KAAK,qBACjBD,QAAQI,UAAU,EAAExB,mBAAmBA,kBACvCoB,QAAQI,UAAU,EAAEC,SAASxB,UAAU;oBAEzC,IAAImB,QAAQM,SAAS,EAAE;wBACrB,yBAAyB;wBACzB,IAAI;4BACF,MAAMC,eAAeZ,SAASa,iBAAiB,CAACR,QAAQM,SAAS,EAAER;4BACnE,IAAIS,cAAc;gCAChBL,gBAAgB;gCAChB;4BACF;wBACF,EAAE,OAAOO,OAAO;4BACdvB,QAAQU,MAAM,CAACa,KAAK,CAAC;gCACnBC,YAAYb,SAASc,EAAE;gCACvBL,WAAWN,QAAQM,SAAS;gCAC5BG,OAAOA,iBAAiBxB,QAAQwB,MAAMG,OAAO,GAAG;4BAClD,GAAG;wBACL;oBACF,OAAO;wBACL,oCAAoC;wBACpCV,gBAAgB;wBAChB;oBACF;gBACF;YACF;YAEA,IAAI,CAACA,eAAe;gBAClBhB,QAAQU,MAAM,CAACiB,KAAK,CAAC;oBACnBH,YAAYb,SAASc,EAAE;oBACvBrB,YAAYV;oBACZC;gBACF,GAAG;gBACH;YACF;YAEA,IAAI;gBACF,8DAA8D;gBAC9D,MAAMc,SAASmB,OAAO,CAACjB,UAAiBC,SAASf;gBACjDG,QAAQU,MAAM,CAACmB,IAAI,CAAC;oBAClBL,YAAYb,SAASc,EAAE;oBACvBrB,YAAYV;oBACZC;gBACF,GAAG;YACL,EAAE,OAAO4B,OAAO;gBACdvB,QAAQU,MAAM,CAACa,KAAK,CAAC;oBACnBC,YAAYb,SAASc,EAAE;oBACvBrB,YAAYV;oBACZC;oBACA4B,OAAOA,iBAAiBxB,QAAQwB,MAAMG,OAAO,GAAG;gBAClD,GAAG;YACH,yDAAyD;YAC3D;QACF;IACF;AACF,EAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xtr-dev/payload-automation",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.39",
|
|
4
4
|
"description": "PayloadCMS Automation Plugin - Comprehensive workflow automation system with visual workflow building, execution tracking, and step types",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dist"
|
|
48
48
|
],
|
|
49
49
|
"scripts": {
|
|
50
|
-
"build": "pnpm copyfiles && pnpm build:
|
|
50
|
+
"build": "pnpm copyfiles && pnpm build:swc",
|
|
51
51
|
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
|
52
52
|
"build:types": "tsc --outDir dist --rootDir ./src",
|
|
53
53
|
"clean": "rimraf {dist,*.tsbuildinfo}",
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
"@payloadcms/ui": "3.45.0",
|
|
76
76
|
"@playwright/test": "^1.52.0",
|
|
77
77
|
"@swc/cli": "0.6.0",
|
|
78
|
+
"@types/handlebars": "^4.1.0",
|
|
78
79
|
"@types/nock": "^11.1.0",
|
|
79
80
|
"@types/node": "^22.5.4",
|
|
80
81
|
"@types/node-cron": "^3.0.11",
|
|
@@ -135,7 +136,7 @@
|
|
|
135
136
|
"registry": "https://registry.npmjs.org/",
|
|
136
137
|
"packageManager": "pnpm@10.12.4+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184",
|
|
137
138
|
"dependencies": {
|
|
138
|
-
"
|
|
139
|
+
"handlebars": "^4.7.8",
|
|
139
140
|
"node-cron": "^4.2.1",
|
|
140
141
|
"pino": "^9.9.0"
|
|
141
142
|
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { Payload, PayloadRequest } from 'payload';
|
|
2
|
-
export interface CustomTriggerOptions {
|
|
3
|
-
/**
|
|
4
|
-
* Data to pass to the workflow execution context
|
|
5
|
-
*/
|
|
6
|
-
data?: Record<string, unknown>;
|
|
7
|
-
/**
|
|
8
|
-
* Optional PayloadRequest to use for the workflow execution
|
|
9
|
-
* If not provided, a minimal request will be created
|
|
10
|
-
*/
|
|
11
|
-
req?: PayloadRequest;
|
|
12
|
-
/**
|
|
13
|
-
* The slug of the custom trigger to execute
|
|
14
|
-
*/
|
|
15
|
-
slug: string;
|
|
16
|
-
/**
|
|
17
|
-
* Optional user information for tracking who triggered the workflow
|
|
18
|
-
*/
|
|
19
|
-
user?: {
|
|
20
|
-
email?: string;
|
|
21
|
-
id?: string;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export interface TriggerResult {
|
|
25
|
-
error?: string;
|
|
26
|
-
runId: number | string;
|
|
27
|
-
status: 'failed' | 'triggered';
|
|
28
|
-
workflowId: string;
|
|
29
|
-
workflowName: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Programmatically trigger workflows that have a matching custom trigger
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```typescript
|
|
36
|
-
* // In your onInit or elsewhere in your code
|
|
37
|
-
* await triggerCustomWorkflow(payload, {
|
|
38
|
-
* slug: 'data-import',
|
|
39
|
-
* data: {
|
|
40
|
-
* source: 'external-api',
|
|
41
|
-
* recordCount: 100,
|
|
42
|
-
* importedAt: new Date().toISOString()
|
|
43
|
-
* }
|
|
44
|
-
* })
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export declare function triggerCustomWorkflow(payload: Payload, options: CustomTriggerOptions): Promise<TriggerResult[]>;
|
|
48
|
-
/**
|
|
49
|
-
* Helper function to trigger a single workflow by ID with custom trigger data
|
|
50
|
-
* This is useful when you know exactly which workflow you want to trigger
|
|
51
|
-
*/
|
|
52
|
-
export declare function triggerWorkflowById(payload: Payload, workflowId: string, triggerSlug: string, data?: Record<string, unknown>, req?: PayloadRequest): Promise<TriggerResult>;
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import type { Payload, PayloadRequest } from 'payload';
|
|
2
|
-
export type PayloadWorkflow = {
|
|
3
|
-
id: number;
|
|
4
|
-
name: string;
|
|
5
|
-
description?: null | string;
|
|
6
|
-
triggers?: Array<{
|
|
7
|
-
type?: null | string;
|
|
8
|
-
condition?: null | string;
|
|
9
|
-
parameters?: {
|
|
10
|
-
collectionSlug?: null | string;
|
|
11
|
-
operation?: null | string;
|
|
12
|
-
global?: null | string;
|
|
13
|
-
globalOperation?: null | string;
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
} | null;
|
|
16
|
-
[key: string]: unknown;
|
|
17
|
-
}> | null;
|
|
18
|
-
steps?: Array<{
|
|
19
|
-
step?: null | string;
|
|
20
|
-
name?: null | string;
|
|
21
|
-
input?: unknown;
|
|
22
|
-
dependencies?: null | string[];
|
|
23
|
-
condition?: null | string;
|
|
24
|
-
[key: string]: unknown;
|
|
25
|
-
}> | null;
|
|
26
|
-
[key: string]: unknown;
|
|
27
|
-
};
|
|
28
|
-
export type WorkflowStep = {
|
|
29
|
-
name: string;
|
|
30
|
-
} & NonNullable<PayloadWorkflow['steps']>[0];
|
|
31
|
-
export type WorkflowTrigger = {
|
|
32
|
-
type: string;
|
|
33
|
-
} & NonNullable<PayloadWorkflow['triggers']>[0];
|
|
34
|
-
export interface ExecutionContext {
|
|
35
|
-
steps: Record<string, any>;
|
|
36
|
-
trigger: Record<string, any>;
|
|
37
|
-
}
|
|
38
|
-
export declare class WorkflowExecutor {
|
|
39
|
-
private payload;
|
|
40
|
-
private logger;
|
|
41
|
-
constructor(payload: Payload, logger: Payload['logger']);
|
|
42
|
-
/**
|
|
43
|
-
* Classifies error types based on error messages
|
|
44
|
-
*/
|
|
45
|
-
private classifyErrorType;
|
|
46
|
-
/**
|
|
47
|
-
* Evaluate a step condition using JSONPath
|
|
48
|
-
*/
|
|
49
|
-
private evaluateStepCondition;
|
|
50
|
-
/**
|
|
51
|
-
* Execute a single workflow step
|
|
52
|
-
*/
|
|
53
|
-
private executeStep;
|
|
54
|
-
/**
|
|
55
|
-
* Extracts detailed error information from job logs and input
|
|
56
|
-
*/
|
|
57
|
-
private extractErrorDetailsFromJob;
|
|
58
|
-
/**
|
|
59
|
-
* Parse a condition value (string literal, number, boolean, or JSONPath)
|
|
60
|
-
*/
|
|
61
|
-
private parseConditionValue;
|
|
62
|
-
/**
|
|
63
|
-
* Resolve step execution order based on dependencies
|
|
64
|
-
*/
|
|
65
|
-
private resolveExecutionOrder;
|
|
66
|
-
/**
|
|
67
|
-
* Resolve a JSONPath value from the context
|
|
68
|
-
*/
|
|
69
|
-
private resolveJSONPathValue;
|
|
70
|
-
/**
|
|
71
|
-
* Resolve step input using JSONPath expressions
|
|
72
|
-
*/
|
|
73
|
-
private resolveStepInput;
|
|
74
|
-
/**
|
|
75
|
-
* Safely serialize an object, handling circular references and non-serializable values
|
|
76
|
-
*/
|
|
77
|
-
private safeSerialize;
|
|
78
|
-
/**
|
|
79
|
-
* Update workflow run with current context
|
|
80
|
-
*/
|
|
81
|
-
private updateWorkflowRunContext;
|
|
82
|
-
/**
|
|
83
|
-
* Evaluate a condition using JSONPath and comparison operators
|
|
84
|
-
*/
|
|
85
|
-
evaluateCondition(condition: string, context: ExecutionContext): boolean;
|
|
86
|
-
/**
|
|
87
|
-
* Execute a workflow with the given context
|
|
88
|
-
*/
|
|
89
|
-
execute(workflow: PayloadWorkflow, context: ExecutionContext, req: PayloadRequest): Promise<void>;
|
|
90
|
-
}
|
package/dist/exports/client.d.ts
DELETED
package/dist/exports/fields.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const WorkflowFields: {};
|
package/dist/exports/rsc.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/exports/server.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
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 { createDocumentHandler, deleteDocumentHandler, httpStepHandler, readDocumentHandler, sendEmailHandler, updateDocumentHandler } from '../steps/index.js';
|
|
5
|
-
export { CreateDocumentStepTask, DeleteDocumentStepTask, HttpRequestStepTask, ReadDocumentStepTask, SendEmailStepTask, UpdateDocumentStepTask } from '../steps/index.js';
|
package/dist/exports/views.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const createCollectionTriggerHook: (collectionSlug: string, hookType: string) => (args: any) => Promise<void>;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { CollectionConfig, GlobalConfig, TaskConfig } from "payload";
|
|
2
|
-
import type { Trigger } from "../triggers/types.js";
|
|
3
|
-
export type TriggerConfig = (config: WorkflowsPluginConfig) => Trigger;
|
|
4
|
-
export type WorkflowsPluginConfig<TSlug extends string = string, TGlobal extends string = string> = {
|
|
5
|
-
collectionTriggers?: {
|
|
6
|
-
[key in TSlug]?: {
|
|
7
|
-
[key in keyof CollectionConfig['hooks']]?: true;
|
|
8
|
-
} | true;
|
|
9
|
-
};
|
|
10
|
-
globalTriggers?: {
|
|
11
|
-
[key in TGlobal]?: {
|
|
12
|
-
[key in keyof GlobalConfig['hooks']]?: true;
|
|
13
|
-
} | true;
|
|
14
|
-
};
|
|
15
|
-
enabled?: boolean;
|
|
16
|
-
steps: TaskConfig<string>[];
|
|
17
|
-
triggers?: TriggerConfig[];
|
|
18
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const createGlobalTriggerHook: (globalSlug: string, hookType: string) => (args: any) => Promise<void>;
|
package/dist/plugin/index.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { Config } from 'payload';
|
|
2
|
-
import type { WorkflowsPluginConfig } from "./config-types.js";
|
|
3
|
-
export { getLogger } from './logger.js';
|
|
4
|
-
export declare const workflowsPlugin: <TSlug extends string>(pluginOptions: WorkflowsPluginConfig<TSlug>) => (config: Config) => Config;
|
package/dist/plugin/logger.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Payload } from 'payload';
|
|
2
|
-
/**
|
|
3
|
-
* Get a logger for config-time use (before Payload initialization)
|
|
4
|
-
*/
|
|
5
|
-
export declare function getConfigLogger(): {
|
|
6
|
-
debug: <T>(message: string, ...args: T[]) => void;
|
|
7
|
-
error: <T>(message: string, ...args: T[]) => void;
|
|
8
|
-
info: <T>(message: string, ...args: T[]) => void;
|
|
9
|
-
warn: <T>(message: string, ...args: T[]) => void;
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Initialize the plugin logger using Payload's Pino instance
|
|
13
|
-
* This creates a child logger with plugin identification
|
|
14
|
-
*/
|
|
15
|
-
export declare function initializeLogger(payload: Payload): Payload['logger'];
|
|
16
|
-
/**
|
|
17
|
-
* Get the plugin logger instance
|
|
18
|
-
* Throws error if not initialized
|
|
19
|
-
*/
|
|
20
|
-
export declare function getLogger(): Payload['logger'];
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export declare const CreateDocumentStepTask: {
|
|
2
|
-
slug: "create-document";
|
|
3
|
-
handler: import("payload").TaskHandler<"create-document">;
|
|
4
|
-
inputSchema: ({
|
|
5
|
-
name: string;
|
|
6
|
-
type: "text";
|
|
7
|
-
admin: {
|
|
8
|
-
description: string;
|
|
9
|
-
};
|
|
10
|
-
required: true;
|
|
11
|
-
} | {
|
|
12
|
-
name: string;
|
|
13
|
-
type: "json";
|
|
14
|
-
admin: {
|
|
15
|
-
description: string;
|
|
16
|
-
};
|
|
17
|
-
required: true;
|
|
18
|
-
} | {
|
|
19
|
-
name: string;
|
|
20
|
-
type: "checkbox";
|
|
21
|
-
admin: {
|
|
22
|
-
description: string;
|
|
23
|
-
};
|
|
24
|
-
required?: undefined;
|
|
25
|
-
} | {
|
|
26
|
-
name: string;
|
|
27
|
-
type: "text";
|
|
28
|
-
admin: {
|
|
29
|
-
description: string;
|
|
30
|
-
};
|
|
31
|
-
required?: undefined;
|
|
32
|
-
})[];
|
|
33
|
-
outputSchema: ({
|
|
34
|
-
name: string;
|
|
35
|
-
type: "json";
|
|
36
|
-
admin: {
|
|
37
|
-
description: string;
|
|
38
|
-
};
|
|
39
|
-
} | {
|
|
40
|
-
name: string;
|
|
41
|
-
type: "text";
|
|
42
|
-
admin: {
|
|
43
|
-
description: string;
|
|
44
|
-
};
|
|
45
|
-
})[];
|
|
46
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
export declare const DeleteDocumentStepTask: {
|
|
2
|
-
slug: "delete-document";
|
|
3
|
-
handler: import("payload").TaskHandler<"delete-document">;
|
|
4
|
-
inputSchema: ({
|
|
5
|
-
name: string;
|
|
6
|
-
type: "text";
|
|
7
|
-
admin: {
|
|
8
|
-
description: string;
|
|
9
|
-
};
|
|
10
|
-
required: true;
|
|
11
|
-
} | {
|
|
12
|
-
name: string;
|
|
13
|
-
type: "text";
|
|
14
|
-
admin: {
|
|
15
|
-
description: string;
|
|
16
|
-
};
|
|
17
|
-
required?: undefined;
|
|
18
|
-
} | {
|
|
19
|
-
name: string;
|
|
20
|
-
type: "json";
|
|
21
|
-
admin: {
|
|
22
|
-
description: string;
|
|
23
|
-
};
|
|
24
|
-
required?: undefined;
|
|
25
|
-
})[];
|
|
26
|
-
outputSchema: ({
|
|
27
|
-
name: string;
|
|
28
|
-
type: "json";
|
|
29
|
-
admin: {
|
|
30
|
-
description: string;
|
|
31
|
-
};
|
|
32
|
-
} | {
|
|
33
|
-
name: string;
|
|
34
|
-
type: "number";
|
|
35
|
-
admin: {
|
|
36
|
-
description: string;
|
|
37
|
-
};
|
|
38
|
-
})[];
|
|
39
|
-
};
|