node-red-contrib-aws-sqs-variable 1.0.0
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 +179 -0
- package/aws-sqs-config.html +366 -0
- package/aws-sqs-config.js +272 -0
- package/aws-sqs.html +253 -0
- package/aws-sqs.js +260 -0
- package/examples/advanced-usage.json +267 -0
- package/examples/basic-usage.json +160 -0
- package/package.json +47 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS SQS Configuration Node
|
|
3
|
+
*
|
|
4
|
+
* Provides configuration for AWS SQS operations in Node-RED.
|
|
5
|
+
* Supports IAM roles and access key authentication with context support.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { SQSClient } = require("@aws-sdk/client-sqs");
|
|
9
|
+
|
|
10
|
+
module.exports = function(RED) {
|
|
11
|
+
/**
|
|
12
|
+
* Helper function to get value from different contexts
|
|
13
|
+
* @param {Object} node - Node instance
|
|
14
|
+
* @param {string} value - Value to get
|
|
15
|
+
* @param {string} type - Type of value (str, flow, global, env)
|
|
16
|
+
* @param {Object} msg - Message object
|
|
17
|
+
* @returns {string} Retrieved value
|
|
18
|
+
*/
|
|
19
|
+
function getValueFromContext(node, value, type, msg) {
|
|
20
|
+
if (value === null || value === undefined) return null;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
let result;
|
|
24
|
+
switch (type) {
|
|
25
|
+
case 'flow':
|
|
26
|
+
const flowContext = node.context().flow;
|
|
27
|
+
if (!flowContext) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
result = getNestedValue(flowContext, value);
|
|
31
|
+
break;
|
|
32
|
+
case 'global':
|
|
33
|
+
const globalContext = node.context().global;
|
|
34
|
+
if (!globalContext) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
result = getNestedValue(globalContext, value);
|
|
38
|
+
break;
|
|
39
|
+
case 'env':
|
|
40
|
+
result = process.env[value];
|
|
41
|
+
break;
|
|
42
|
+
case 'msg':
|
|
43
|
+
result = RED.util.getMessageProperty(msg, value);
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
result = value;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return result !== undefined ? result : null;
|
|
50
|
+
} catch (err) {
|
|
51
|
+
throw new Error(`Failed to get value for type: ${type}, value: ${value}. Error: ${err.message}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Helper function to get nested values like "all_vars.host"
|
|
57
|
+
* @param {Object} context - Context object
|
|
58
|
+
* @param {string} path - Dot-separated path
|
|
59
|
+
* @returns {*} Retrieved value
|
|
60
|
+
*/
|
|
61
|
+
function getNestedValue(context, path) {
|
|
62
|
+
if (!context) return undefined;
|
|
63
|
+
|
|
64
|
+
if (path.includes('.')) {
|
|
65
|
+
const parts = path.split('.');
|
|
66
|
+
let result = context.get(parts[0]);
|
|
67
|
+
for (let i = 1; i < parts.length; i++) {
|
|
68
|
+
if (result && typeof result === 'object') {
|
|
69
|
+
result = result[parts[i]];
|
|
70
|
+
} else {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
} else {
|
|
76
|
+
return context.get(path);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* AWS SQS Configuration Node constructor
|
|
82
|
+
*
|
|
83
|
+
* @param {Object} config - Node configuration
|
|
84
|
+
* @param {string} config.name - Node name
|
|
85
|
+
* @param {boolean} config.useIAMRole - Whether to use IAM role
|
|
86
|
+
*/
|
|
87
|
+
function AWSSQSConfigNode(config) {
|
|
88
|
+
RED.nodes.createNode(this, config);
|
|
89
|
+
|
|
90
|
+
this.name = config.name || "AWS SQS Config";
|
|
91
|
+
this.region = config.region || "eu-central-1";
|
|
92
|
+
|
|
93
|
+
// Store credential types and values
|
|
94
|
+
this.useIAMRole = config.useIAMRole === true || config.useIAMRole === "true" || config.useIAMRole === 1;
|
|
95
|
+
this.deferMissingConfig = config.deferMissingConfig === undefined ? true : (config.deferMissingConfig === true || config.deferMissingConfig === "true");
|
|
96
|
+
this.regionType = config.regionType || 'str';
|
|
97
|
+
this.regionContext = config.regionContext;
|
|
98
|
+
this.accessKeyIdType = config.accessKeyIdType || 'str';
|
|
99
|
+
this.secretAccessKeyType = config.secretAccessKeyType || 'str';
|
|
100
|
+
this.accessKeyId = config.accessKeyId;
|
|
101
|
+
this.accessKeyIdContext = config.accessKeyIdContext;
|
|
102
|
+
this.secretAccessKey = config.secretAccessKey;
|
|
103
|
+
this.secretAccessKeyContext = config.secretAccessKeyContext;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Parse credential values based on type
|
|
107
|
+
* @param {string} value - Value to parse
|
|
108
|
+
* @param {string} type - Type of value
|
|
109
|
+
* @param {Object} msg - Message object
|
|
110
|
+
* @param {Object} executingNode - Node executing the request
|
|
111
|
+
* @returns {string|null} Parsed value
|
|
112
|
+
*/
|
|
113
|
+
this.parseCredentialValue = function(value, type, msg, executingNode) {
|
|
114
|
+
if (!value) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
let result;
|
|
120
|
+
switch (type) {
|
|
121
|
+
case 'str':
|
|
122
|
+
result = value;
|
|
123
|
+
break;
|
|
124
|
+
case 'flow':
|
|
125
|
+
result = getValueFromContext(executingNode || this, value, 'flow', msg);
|
|
126
|
+
break;
|
|
127
|
+
case 'global':
|
|
128
|
+
result = getValueFromContext(executingNode || this, value, 'global', msg);
|
|
129
|
+
break;
|
|
130
|
+
case 'env':
|
|
131
|
+
result = process.env[value] || null;
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
result = value;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return result;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (executingNode) {
|
|
140
|
+
executingNode.error(`Error parsing credential value: ${error.message}`);
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Resolve region based on configuration
|
|
148
|
+
* @param {Object} msg - Message object
|
|
149
|
+
* @param {Object} executingNode - Node executing the request
|
|
150
|
+
* @returns {string} Region string
|
|
151
|
+
*/
|
|
152
|
+
this.resolveRegion = function(msg, executingNode) {
|
|
153
|
+
if (this.regionType === 'str') {
|
|
154
|
+
return this.region || process.env.AWS_REGION || "eu-central-1";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const resolved = this.parseCredentialValue(this.regionContext, this.regionType, msg, executingNode);
|
|
158
|
+
return resolved || process.env.AWS_REGION || "eu-central-1";
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get credentials based on configuration
|
|
163
|
+
* @param {Object} msg - Message object
|
|
164
|
+
* @param {Object} executingNode - Node executing the request
|
|
165
|
+
* @returns {Object} Credentials object
|
|
166
|
+
*/
|
|
167
|
+
this.getCredentials = function(msg, executingNode) {
|
|
168
|
+
if (this.useIAMRole) {
|
|
169
|
+
return {
|
|
170
|
+
useIAMRole: true,
|
|
171
|
+
region: this.resolveRegion(msg, executingNode)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
// Handle Access Key ID
|
|
177
|
+
let accessKeyId;
|
|
178
|
+
if (this.accessKeyIdType === 'str') {
|
|
179
|
+
accessKeyId = this.credentials?.accessKeyId;
|
|
180
|
+
} else {
|
|
181
|
+
accessKeyId = this.parseCredentialValue(this.accessKeyIdContext, this.accessKeyIdType, msg, executingNode);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Handle Secret Access Key
|
|
185
|
+
let secretAccessKey;
|
|
186
|
+
if (this.secretAccessKeyType === 'str') {
|
|
187
|
+
secretAccessKey = this.credentials?.secretAccessKey;
|
|
188
|
+
} else {
|
|
189
|
+
secretAccessKey = this.parseCredentialValue(this.secretAccessKeyContext, this.secretAccessKeyType, msg, executingNode);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!accessKeyId || !secretAccessKey) {
|
|
193
|
+
const missingFields = [];
|
|
194
|
+
if (!accessKeyId) missingFields.push('Access Key ID');
|
|
195
|
+
if (!secretAccessKey) missingFields.push('Secret Access Key');
|
|
196
|
+
if (this.deferMissingConfig) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
throw new Error(`Missing required credentials: ${missingFields.join(', ')}`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
accessKeyId,
|
|
204
|
+
secretAccessKey,
|
|
205
|
+
region: this.resolveRegion(msg, executingNode)
|
|
206
|
+
};
|
|
207
|
+
} catch (err) {
|
|
208
|
+
if (this.deferMissingConfig) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
throw new Error(`Failed to get AWS credentials: ${err.message}`);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get AWS SQS client
|
|
217
|
+
* @param {Object} msg - Message object
|
|
218
|
+
* @param {Object} executingNode - Node executing the request
|
|
219
|
+
* @returns {SQSClient} AWS SQS client
|
|
220
|
+
*/
|
|
221
|
+
this.getClient = (msg, executingNode) => {
|
|
222
|
+
try {
|
|
223
|
+
if (this.useIAMRole) {
|
|
224
|
+
return new SQSClient({
|
|
225
|
+
region: this.resolveRegion(msg, executingNode)
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const credentials = this.getCredentials(msg, executingNode);
|
|
230
|
+
if (!credentials) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return new SQSClient({
|
|
235
|
+
region: credentials.region,
|
|
236
|
+
credentials: {
|
|
237
|
+
accessKeyId: credentials.accessKeyId,
|
|
238
|
+
secretAccessKey: credentials.secretAccessKey
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
} catch (error) {
|
|
243
|
+
if (executingNode) {
|
|
244
|
+
executingNode.error(`Failed to create SQS client: ${error.message}`);
|
|
245
|
+
}
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Register node type with credentials
|
|
252
|
+
RED.nodes.registerType("aws-sqs-config", AWSSQSConfigNode, {
|
|
253
|
+
credentials: {
|
|
254
|
+
accessKeyId: { type: "text" },
|
|
255
|
+
secretAccessKey: { type: "password" }
|
|
256
|
+
},
|
|
257
|
+
defaults: {
|
|
258
|
+
name: { value: "" },
|
|
259
|
+
region: { value: "eu-central-1", required: true },
|
|
260
|
+
regionType: { value: "str" },
|
|
261
|
+
regionContext: { value: "" },
|
|
262
|
+
useIAMRole: { value: false, required: true },
|
|
263
|
+
deferMissingConfig: { value: true },
|
|
264
|
+
accessKeyId: { value: "" },
|
|
265
|
+
accessKeyIdType: { value: "str" },
|
|
266
|
+
accessKeyIdContext: { value: "" },
|
|
267
|
+
secretAccessKey: { value: "" },
|
|
268
|
+
secretAccessKeyType: { value: "str" },
|
|
269
|
+
secretAccessKeyContext: { value: "" }
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
};
|
package/aws-sqs.html
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType("aws-sqs", {
|
|
3
|
+
category: "AWS",
|
|
4
|
+
color: "#b2e2b2",
|
|
5
|
+
defaults: {
|
|
6
|
+
name: { value: "" },
|
|
7
|
+
awsConfig: { value: "", type: "aws-sqs-config", required: true },
|
|
8
|
+
operation: { value: "send", required: true },
|
|
9
|
+
queueUrl: { value: "" },
|
|
10
|
+
queueUrlType: { value: "str" },
|
|
11
|
+
messageBody: { value: "payload" },
|
|
12
|
+
messageBodyType: { value: "msg" },
|
|
13
|
+
messageGroupId: { value: "" },
|
|
14
|
+
messageGroupIdType: { value: "str" },
|
|
15
|
+
messageDeduplicationId: { value: "" },
|
|
16
|
+
messageDeduplicationIdType: { value: "str" },
|
|
17
|
+
maxNumberOfMessages: { value: 1 },
|
|
18
|
+
waitTimeSeconds: { value: 0 },
|
|
19
|
+
visibilityTimeout: { value: 30 },
|
|
20
|
+
deleteAfterReceive: { value: true },
|
|
21
|
+
parseJsonBody: { value: false },
|
|
22
|
+
pollEnabled: { value: false },
|
|
23
|
+
pollIntervalSeconds: { value: 30 }
|
|
24
|
+
},
|
|
25
|
+
inputs: 1,
|
|
26
|
+
outputs: 1,
|
|
27
|
+
icon: "font-awesome/fa-exchange",
|
|
28
|
+
label: function() {
|
|
29
|
+
return this.name || "AWS SQS (" + this.operation + ")";
|
|
30
|
+
},
|
|
31
|
+
oneditprepare: function() {
|
|
32
|
+
// Initialize typedInput for Queue URL
|
|
33
|
+
$("#node-input-queueUrl").typedInput({
|
|
34
|
+
default: 'str',
|
|
35
|
+
types: ['str', 'msg', 'flow', 'global', 'env'],
|
|
36
|
+
typeField: "#node-input-queueUrlType"
|
|
37
|
+
});
|
|
38
|
+
$("#node-input-queueUrl").typedInput('type', this.queueUrlType || 'str');
|
|
39
|
+
$("#node-input-queueUrl").typedInput('value', this.queueUrl || '');
|
|
40
|
+
|
|
41
|
+
// Initialize typedInput for Message Body
|
|
42
|
+
$("#node-input-messageBody").typedInput({
|
|
43
|
+
default: 'msg',
|
|
44
|
+
types: ['msg', 'str', 'flow', 'global', 'env'],
|
|
45
|
+
typeField: "#node-input-messageBodyType"
|
|
46
|
+
});
|
|
47
|
+
$("#node-input-messageBody").typedInput('type', this.messageBodyType || 'msg');
|
|
48
|
+
$("#node-input-messageBody").typedInput('value', this.messageBody || 'payload');
|
|
49
|
+
|
|
50
|
+
// Initialize typedInput for Message Group ID (FIFO)
|
|
51
|
+
$("#node-input-messageGroupId").typedInput({
|
|
52
|
+
default: 'str',
|
|
53
|
+
types: ['str', 'msg', 'flow', 'global', 'env'],
|
|
54
|
+
typeField: "#node-input-messageGroupIdType"
|
|
55
|
+
});
|
|
56
|
+
$("#node-input-messageGroupId").typedInput('type', this.messageGroupIdType || 'str');
|
|
57
|
+
$("#node-input-messageGroupId").typedInput('value', this.messageGroupId || '');
|
|
58
|
+
|
|
59
|
+
// Initialize typedInput for Message Deduplication ID (FIFO)
|
|
60
|
+
$("#node-input-messageDeduplicationId").typedInput({
|
|
61
|
+
default: 'str',
|
|
62
|
+
types: ['str', 'msg', 'flow', 'global', 'env'],
|
|
63
|
+
typeField: "#node-input-messageDeduplicationIdType"
|
|
64
|
+
});
|
|
65
|
+
$("#node-input-messageDeduplicationId").typedInput('type', this.messageDeduplicationIdType || 'str');
|
|
66
|
+
$("#node-input-messageDeduplicationId").typedInput('value', this.messageDeduplicationId || '');
|
|
67
|
+
|
|
68
|
+
// Initialize tooltips
|
|
69
|
+
$('.node-input').tooltip({
|
|
70
|
+
delay: { show: 500, hide: 100 },
|
|
71
|
+
trigger: 'hover'
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
var updateOperationFields = function() {
|
|
75
|
+
var operation = $("#node-input-operation").val();
|
|
76
|
+
if (operation === "send") {
|
|
77
|
+
$("#sendFields").show();
|
|
78
|
+
$("#receiveFields").hide();
|
|
79
|
+
} else {
|
|
80
|
+
$("#sendFields").hide();
|
|
81
|
+
$("#receiveFields").show();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
$("#node-input-operation").on("change", updateOperationFields);
|
|
86
|
+
updateOperationFields();
|
|
87
|
+
},
|
|
88
|
+
oneditsave: function() {
|
|
89
|
+
this.queueUrlType = $("#node-input-queueUrlType").val();
|
|
90
|
+
this.queueUrl = $("#node-input-queueUrl").typedInput('value');
|
|
91
|
+
this.messageBodyType = $("#node-input-messageBodyType").val();
|
|
92
|
+
this.messageBody = $("#node-input-messageBody").typedInput('value');
|
|
93
|
+
this.messageGroupIdType = $("#node-input-messageGroupIdType").val();
|
|
94
|
+
this.messageGroupId = $("#node-input-messageGroupId").typedInput('value');
|
|
95
|
+
this.messageDeduplicationIdType = $("#node-input-messageDeduplicationIdType").val();
|
|
96
|
+
this.messageDeduplicationId = $("#node-input-messageDeduplicationId").typedInput('value');
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<script type="text/x-red" data-template-name="aws-sqs">
|
|
102
|
+
<div class="form-row">
|
|
103
|
+
<label for="node-input-name">
|
|
104
|
+
<i class="fa fa-tag"></i> Name
|
|
105
|
+
</label>
|
|
106
|
+
<input type="text" id="node-input-name" placeholder="AWS SQS" style="width: 70%;">
|
|
107
|
+
</div>
|
|
108
|
+
<div class="form-row">
|
|
109
|
+
<label for="node-input-awsConfig">
|
|
110
|
+
<i class="fa fa-cog"></i> AWS Config
|
|
111
|
+
</label>
|
|
112
|
+
<input type="text" id="node-input-awsConfig" style="width: 70%;">
|
|
113
|
+
</div>
|
|
114
|
+
<div class="form-row">
|
|
115
|
+
<label for="node-input-operation">
|
|
116
|
+
<i class="fa fa-exchange"></i> Operation
|
|
117
|
+
</label>
|
|
118
|
+
<select id="node-input-operation" style="width: 70%;">
|
|
119
|
+
<option value="send">Send Message</option>
|
|
120
|
+
<option value="receive">Receive Messages</option>
|
|
121
|
+
</select>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="form-row">
|
|
124
|
+
<label for="node-input-queueUrl">
|
|
125
|
+
<i class="fa fa-link"></i> Queue URL
|
|
126
|
+
</label>
|
|
127
|
+
<input type="text" id="node-input-queueUrl" style="width: 70%;">
|
|
128
|
+
<input type="hidden" id="node-input-queueUrlType">
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<div id="sendFields">
|
|
132
|
+
<div class="form-row">
|
|
133
|
+
<label for="node-input-messageBody">
|
|
134
|
+
<i class="fa fa-envelope"></i> Message Body
|
|
135
|
+
</label>
|
|
136
|
+
<input type="text" id="node-input-messageBody" style="width: 70%;">
|
|
137
|
+
<input type="hidden" id="node-input-messageBodyType">
|
|
138
|
+
</div>
|
|
139
|
+
<div class="form-row">
|
|
140
|
+
<label for="node-input-messageGroupId">
|
|
141
|
+
<i class="fa fa-object-group"></i> Message Group ID
|
|
142
|
+
</label>
|
|
143
|
+
<input type="text" id="node-input-messageGroupId" style="width: 70%;">
|
|
144
|
+
<input type="hidden" id="node-input-messageGroupIdType">
|
|
145
|
+
</div>
|
|
146
|
+
<div class="form-row">
|
|
147
|
+
<label for="node-input-messageDeduplicationId">
|
|
148
|
+
<i class="fa fa-clone"></i> Deduplication ID
|
|
149
|
+
</label>
|
|
150
|
+
<input type="text" id="node-input-messageDeduplicationId" style="width: 70%;">
|
|
151
|
+
<input type="hidden" id="node-input-messageDeduplicationIdType">
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div id="receiveFields" style="display: none;">
|
|
156
|
+
<div class="form-row">
|
|
157
|
+
<label for="node-input-pollEnabled">
|
|
158
|
+
<i class="fa fa-refresh"></i> Polling
|
|
159
|
+
</label>
|
|
160
|
+
<input type="checkbox" id="node-input-pollEnabled" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
161
|
+
<span style="margin-left: 5px; vertical-align: middle;">Enable regular polling</span>
|
|
162
|
+
</div>
|
|
163
|
+
<div class="form-row">
|
|
164
|
+
<label for="node-input-pollIntervalSeconds">
|
|
165
|
+
<i class="fa fa-clock-o"></i> Poll Interval (s)
|
|
166
|
+
</label>
|
|
167
|
+
<input type="number" id="node-input-pollIntervalSeconds" min="1" max="86400" style="width: 70%;">
|
|
168
|
+
</div>
|
|
169
|
+
<div class="form-row">
|
|
170
|
+
<label for="node-input-maxNumberOfMessages">
|
|
171
|
+
<i class="fa fa-list"></i> Max Messages
|
|
172
|
+
</label>
|
|
173
|
+
<input type="number" id="node-input-maxNumberOfMessages" min="1" max="10" style="width: 70%;">
|
|
174
|
+
</div>
|
|
175
|
+
<div class="form-row">
|
|
176
|
+
<label for="node-input-waitTimeSeconds">
|
|
177
|
+
<i class="fa fa-clock-o"></i> Wait Time (s)
|
|
178
|
+
</label>
|
|
179
|
+
<input type="number" id="node-input-waitTimeSeconds" min="0" max="20" style="width: 70%;">
|
|
180
|
+
</div>
|
|
181
|
+
<div class="form-row">
|
|
182
|
+
<label for="node-input-visibilityTimeout">
|
|
183
|
+
<i class="fa fa-eye-slash"></i> Visibility Timeout (s)
|
|
184
|
+
</label>
|
|
185
|
+
<input type="number" id="node-input-visibilityTimeout" min="0" max="43200" style="width: 70%;">
|
|
186
|
+
</div>
|
|
187
|
+
<div class="form-row">
|
|
188
|
+
<label for="node-input-deleteAfterReceive">
|
|
189
|
+
<i class="fa fa-trash"></i> Delete After Receive
|
|
190
|
+
</label>
|
|
191
|
+
<input type="checkbox" id="node-input-deleteAfterReceive" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
192
|
+
<span style="margin-left: 5px; vertical-align: middle;">Delete messages from queue after read</span>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="form-row">
|
|
195
|
+
<label for="node-input-parseJsonBody">
|
|
196
|
+
<i class="fa fa-code"></i> Parse JSON Body
|
|
197
|
+
</label>
|
|
198
|
+
<input type="checkbox" id="node-input-parseJsonBody" style="display: inline-block; width: auto; vertical-align: middle;">
|
|
199
|
+
<span style="margin-left: 5px; vertical-align: middle;">Parse message body as JSON when possible</span>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
</script>
|
|
203
|
+
|
|
204
|
+
<script type="text/x-red" data-help-name="aws-sqs">
|
|
205
|
+
<p>A Node-RED node for AWS SQS operations.</p>
|
|
206
|
+
|
|
207
|
+
<h3>Configuration</h3>
|
|
208
|
+
<p>Select or create an AWS SQS configuration that contains your AWS credentials and region settings.</p>
|
|
209
|
+
|
|
210
|
+
<h3>Queue URL Input</h3>
|
|
211
|
+
<p>The Queue URL field supports multiple input types:</p>
|
|
212
|
+
<ul>
|
|
213
|
+
<li><b>String</b>: Direct Queue URL</li>
|
|
214
|
+
<li><b>Message</b>: Retrieved from message property (e.g., <code>payload.queueUrl</code>)</li>
|
|
215
|
+
<li><b>Flow Context</b>: Retrieved from flow context</li>
|
|
216
|
+
<li><b>Global Context</b>: Retrieved from global context</li>
|
|
217
|
+
<li><b>Environment Variable</b>: Retrieved from environment variable</li>
|
|
218
|
+
</ul>
|
|
219
|
+
|
|
220
|
+
<h3>Operations</h3>
|
|
221
|
+
<ul>
|
|
222
|
+
<li><b>Send Message</b>: Sends a message to the queue</li>
|
|
223
|
+
<li><b>Receive Messages</b>: Receives messages from the queue</li>
|
|
224
|
+
</ul>
|
|
225
|
+
|
|
226
|
+
<h3>FIFO Notes</h3>
|
|
227
|
+
<ul>
|
|
228
|
+
<li>For FIFO queues, <b>Message Group ID</b> is required</li>
|
|
229
|
+
<li>Deduplication ID is optional if content-based deduplication is enabled</li>
|
|
230
|
+
</ul>
|
|
231
|
+
|
|
232
|
+
<h3>Output</h3>
|
|
233
|
+
<p>Send operation returns message metadata. Receive operation returns array of messages in <code>msg.payload</code>.</p>
|
|
234
|
+
</script>
|
|
235
|
+
|
|
236
|
+
<style>
|
|
237
|
+
.help-text {
|
|
238
|
+
font-size: 0.8em;
|
|
239
|
+
color: #666;
|
|
240
|
+
margin-top: 4px;
|
|
241
|
+
}
|
|
242
|
+
.error-text {
|
|
243
|
+
color: #d00;
|
|
244
|
+
font-size: 0.8em;
|
|
245
|
+
margin-top: 4px;
|
|
246
|
+
}
|
|
247
|
+
.input-error {
|
|
248
|
+
border-color: #d00 !important;
|
|
249
|
+
}
|
|
250
|
+
.form-row {
|
|
251
|
+
margin-bottom: 10px;
|
|
252
|
+
}
|
|
253
|
+
</style>
|