@5minds/node-red-contrib-processcube 1.16.1-develop-36f966-mh90fmsz → 1.16.1-feature-5e019f-mhojvcvu
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/externaltask-error.js +3 -3
- package/externaltask-inject.html +123 -0
- package/externaltask-inject.js +98 -0
- package/package.json +2 -1
package/externaltask-error.js
CHANGED
|
@@ -3,10 +3,10 @@ module.exports = function (RED) {
|
|
|
3
3
|
RED.nodes.createNode(this, config);
|
|
4
4
|
var node = this;
|
|
5
5
|
|
|
6
|
-
node.on('input', function (msg) {
|
|
6
|
+
node.on('input', function (msg) {
|
|
7
7
|
const flowNodeInstanceId = msg.flowNodeInstanceId;
|
|
8
8
|
const etw_input_node_id = msg.etw_input_node_id;
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
if (!etw_input_node_id) {
|
|
11
11
|
node.error('Error: The message did not contain the required etw_input_node_id.');
|
|
12
12
|
} else {
|
|
@@ -24,7 +24,7 @@ module.exports = function (RED) {
|
|
|
24
24
|
if (msgError.code) {
|
|
25
25
|
errorCode = msgError.code;
|
|
26
26
|
errorMessage = msgError.message;
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
28
|
} else if (msg.errorCode) {
|
|
29
29
|
errorCode = msg.errorCode;
|
|
30
30
|
errorMessage = msg.errorMessage;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('externaltask-inject', {
|
|
3
|
+
category: 'ProcessCube',
|
|
4
|
+
color: '#02AFD6',
|
|
5
|
+
defaults: {
|
|
6
|
+
name: { value: '' },
|
|
7
|
+
payloadType: { value: 'json' },
|
|
8
|
+
payload: { value: '{}' },
|
|
9
|
+
taskType: { value: 'json' },
|
|
10
|
+
task: { value: '{}' }
|
|
11
|
+
},
|
|
12
|
+
inputs: 0,
|
|
13
|
+
outputs: 1,
|
|
14
|
+
icon: 'inject.svg',
|
|
15
|
+
label: function () {
|
|
16
|
+
return this.name || 'externaltask-inject';
|
|
17
|
+
},
|
|
18
|
+
button: {
|
|
19
|
+
onclick: function() {
|
|
20
|
+
var node = this;
|
|
21
|
+
|
|
22
|
+
$.ajax({
|
|
23
|
+
type: "POST",
|
|
24
|
+
url: "externaltask-inject/trigger/" + node.id,
|
|
25
|
+
success: function(resp) {
|
|
26
|
+
RED.notify("Message injected", "success");
|
|
27
|
+
},
|
|
28
|
+
error: function(xhr, status, err) {
|
|
29
|
+
RED.notify("Error injecting message: " + err, "error");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
oneditprepare: function () {
|
|
35
|
+
// Initialize the typed input for payload
|
|
36
|
+
$('#node-input-payload').typedInput({
|
|
37
|
+
default: 'json',
|
|
38
|
+
types: ['str', 'num', 'bool', 'json', 'jsonata', 'flow', 'global']
|
|
39
|
+
});
|
|
40
|
+
// Restore the saved type for payload from hidden input
|
|
41
|
+
var payloadType = $('#node-input-payloadType').val();
|
|
42
|
+
if (payloadType) {
|
|
43
|
+
$('#node-input-payload').typedInput('type', payloadType);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Initialize the typed input for task
|
|
47
|
+
$('#node-input-task').typedInput({
|
|
48
|
+
default: 'json',
|
|
49
|
+
types: ['str', 'num', 'bool', 'json', 'jsonata', 'flow', 'global']
|
|
50
|
+
});
|
|
51
|
+
// Restore the saved type for task from hidden input
|
|
52
|
+
var taskType = $('#node-input-taskType').val();
|
|
53
|
+
if (taskType) {
|
|
54
|
+
$('#node-input-task').typedInput('type', taskType);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
oneditsave: function () {
|
|
58
|
+
var payloadValue = $('#node-input-payload').typedInput('value');
|
|
59
|
+
var payloadType = $('#node-input-payload').typedInput('type');
|
|
60
|
+
this.payload = payloadValue;
|
|
61
|
+
this.payloadType = payloadType;
|
|
62
|
+
// Persist type to hidden input field
|
|
63
|
+
$('#node-input-payloadType').val(payloadType);
|
|
64
|
+
|
|
65
|
+
var taskValue = $('#node-input-task').typedInput('value');
|
|
66
|
+
var taskType = $('#node-input-task').typedInput('type');
|
|
67
|
+
this.task = taskValue;
|
|
68
|
+
this.taskType = taskType;
|
|
69
|
+
// Persist type to hidden input field
|
|
70
|
+
$('#node-input-taskType').val(taskType);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<script type="text/html" data-template-name="externaltask-inject">
|
|
76
|
+
<div class="form-row">
|
|
77
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
78
|
+
<input type="text" id="node-input-name" placeholder="Name" />
|
|
79
|
+
</div>
|
|
80
|
+
<div class="form-row">
|
|
81
|
+
<label for="node-input-payload">msg.payload</label>
|
|
82
|
+
<input type="hidden" id="node-input-payloadType">
|
|
83
|
+
<input type="text" id="node-input-payload" style="width: 70%;">
|
|
84
|
+
</div>
|
|
85
|
+
<div class="form-row">
|
|
86
|
+
<label for="node-input-task">msg.task</label>
|
|
87
|
+
<input type="hidden" id="node-input-taskType">
|
|
88
|
+
<input type="text" id="node-input-task" style="width: 70%;">
|
|
89
|
+
</div>
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<script type="text/markdown" data-help-name="externaltask-inject">
|
|
93
|
+
A lightweight alternative to the standard Node-RED inject node for testing external task workflows. Use this node to inject test messages directly into an external task workflow without needing a real external task from the ProcessCube engine.
|
|
94
|
+
|
|
95
|
+
This node is ideal for small-scale testing and debugging of external task workflows. For larger-scale testing with test cases or CI/CD integration, use the **externaltask-testing** node instead.
|
|
96
|
+
|
|
97
|
+
## Features
|
|
98
|
+
|
|
99
|
+
- Injects messages with configurable payload and task metadata
|
|
100
|
+
- Automatically generates `flowNodeInstanceId` and `processInstanceId` if not provided
|
|
101
|
+
- Sets required fields for compatibility with externaltask-output and externaltask-error nodes
|
|
102
|
+
- Supports multiple value types (JSON, string, number, boolean, JSONata, flow/global context)
|
|
103
|
+
|
|
104
|
+
## Configs
|
|
105
|
+
|
|
106
|
+
: name (string) : The name of the node
|
|
107
|
+
: payload (string | {}) : The payload to inject into the workflow
|
|
108
|
+
: task (string | {}) : The task object to inject
|
|
109
|
+
|
|
110
|
+
## Outputs
|
|
111
|
+
|
|
112
|
+
: payload (string | {}) : The injected payload with metadata (flowNodeInstanceId, processInstanceId, task)
|
|
113
|
+
: task (object) : The injected task object
|
|
114
|
+
: flowNodeInstanceId (string) : Unique identifier for the external task
|
|
115
|
+
: processInstanceId (string) : Reference to the process instance
|
|
116
|
+
: etw_input_node_id (string) : Reference to the injecting node
|
|
117
|
+
: etw_started_at (string) : ISO timestamp of when the task was injected
|
|
118
|
+
|
|
119
|
+
## References
|
|
120
|
+
|
|
121
|
+
- [The ProcessCube© Developer Network](https://processcube.io) - All documentation for the ProcessCube© platform
|
|
122
|
+
- [ProcessCube© LowCode Integration](https://processcube.io/docs/node-red) - LowCode integration in ProcessCube©
|
|
123
|
+
</script>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const { v4: uuidv4 } = require('uuid');
|
|
2
|
+
const EventEmitter = require('node:events');
|
|
3
|
+
|
|
4
|
+
module.exports = function (RED) {
|
|
5
|
+
function ExternalTaskInject(config) {
|
|
6
|
+
RED.nodes.createNode(this, config);
|
|
7
|
+
var node = this;
|
|
8
|
+
node.config = config;
|
|
9
|
+
node.eventEmitter = new EventEmitter();
|
|
10
|
+
|
|
11
|
+
node.on('input', function (msg, send, done) {
|
|
12
|
+
msg.flowNodeInstanceId = msg.flowNodeInstanceId ?? uuidv4();
|
|
13
|
+
msg.processInstanceId = msg.processInstanceId ?? uuidv4();
|
|
14
|
+
|
|
15
|
+
if (!msg.task) {
|
|
16
|
+
// Use configured task if available, otherwise create default
|
|
17
|
+
if (config.task) {
|
|
18
|
+
msg.task = config.task;
|
|
19
|
+
} else {
|
|
20
|
+
msg.task = {
|
|
21
|
+
flowNodeInstanceId: msg.flowNodeInstanceId,
|
|
22
|
+
processInstanceId: msg.processInstanceId,
|
|
23
|
+
task: {}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
msg.etw_started_at = new Date().toISOString();
|
|
28
|
+
msg.etw_input_node_id = node.id;
|
|
29
|
+
|
|
30
|
+
send(msg);
|
|
31
|
+
if (done) done();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
RED.nodes.registerType('externaltask-inject', ExternalTaskInject);
|
|
37
|
+
|
|
38
|
+
// Helper function to parse typed values
|
|
39
|
+
function parseTypedValue(value, type) {
|
|
40
|
+
switch(type) {
|
|
41
|
+
case 'str':
|
|
42
|
+
return value || '';
|
|
43
|
+
case 'num':
|
|
44
|
+
return Number(value) || 0;
|
|
45
|
+
case 'bool':
|
|
46
|
+
return value === 'true' || value === true;
|
|
47
|
+
case 'json':
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(value || '{}');
|
|
50
|
+
} catch(parseErr) {
|
|
51
|
+
console.error("Invalid JSON: " + parseErr.message);
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
case 'jsonata':
|
|
55
|
+
// JSONata expressions would need to be evaluated in Node-RED context
|
|
56
|
+
// For now, treat as string
|
|
57
|
+
return value || '';
|
|
58
|
+
case 'flow':
|
|
59
|
+
case 'global':
|
|
60
|
+
// These are context references - store as string for now
|
|
61
|
+
return value || '';
|
|
62
|
+
default:
|
|
63
|
+
return value || '';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// HTTP endpoint to handle button clicks
|
|
68
|
+
RED.httpAdmin.post('/externaltask-inject/trigger/:id', function(req, res) {
|
|
69
|
+
var node = RED.nodes.getNode(req.params.id);
|
|
70
|
+
if (node !== null && typeof node !== 'undefined') {
|
|
71
|
+
try {
|
|
72
|
+
var payloadValue = node.config.payload;
|
|
73
|
+
var payloadType = node.config.payloadType || 'json';
|
|
74
|
+
var payloadData = parseTypedValue(payloadValue, payloadType);
|
|
75
|
+
|
|
76
|
+
var taskValue = node.config.task;
|
|
77
|
+
var taskType = node.config.taskType || 'json';
|
|
78
|
+
var taskData = parseTypedValue(taskValue, taskType);
|
|
79
|
+
|
|
80
|
+
// Create a message with the configured payload and task
|
|
81
|
+
var msg = {
|
|
82
|
+
payload: payloadData,
|
|
83
|
+
task: taskData,
|
|
84
|
+
_msgid: uuidv4()
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Trigger the node's input handler with the configured message
|
|
88
|
+
node.receive(msg);
|
|
89
|
+
res.sendStatus(200);
|
|
90
|
+
} catch(err) {
|
|
91
|
+
res.sendStatus(500);
|
|
92
|
+
node.error("Error injecting message: " + err.message);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
res.sendStatus(404);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@5minds/node-red-contrib-processcube",
|
|
3
|
-
"version": "1.16.1-
|
|
3
|
+
"version": "1.16.1-feature-5e019f-mhojvcvu",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Node-RED nodes for ProcessCube",
|
|
6
6
|
"scripts": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"DataobjectInstanceQuery": "dataobject-instance-query.js",
|
|
40
40
|
"EndEventFinishedListener": "endevent-finished-listener.js",
|
|
41
41
|
"externaltaskInput": "externaltask-input.js",
|
|
42
|
+
"externaltaskInject": "externaltask-inject.js",
|
|
42
43
|
"externaltaskOutput": "externaltask-output.js",
|
|
43
44
|
"externaltaskError": "externaltask-error.js",
|
|
44
45
|
"externaltaskEventListener": "externaltask-event-listener.js",
|