@apidaze/node-red-contrib-apidaze
Version:
Node-RED module for Apidaze
147 lines (121 loc) • 3.97 kB
JavaScript
module.exports = function (RED) {
'use strict';
const jsonata = require('jsonata');
const { Parser } = require('xml2js');
const callsDb = require('../../helpers/call-store');
const parser = new Parser({
attrkey: '_',
charkey: 'z',
mergeAttrs: false,
explicitArray: false,
explicitRoot: false,
});
const operations = {
contains: (value1, value2) => value1.toString().includes(value2.toString()),
notContains: (value1, value2) =>
!value1.toString().includes(value2.toString()),
equal: (value1, value2) => value1 === value2,
notEqual: (value1, value2) => value1 !== value2,
regex: (value1, value2) => {
const regexMatch = value2
.toString()
.match(new RegExp('^/(.*?)/([gimy]*)$'));
let regex;
if (!regexMatch) {
regex = new RegExp(value2.toString());
} else if (regexMatch.length === 1) {
regex = new RegExp(regexMatch[1]);
} else {
regex = new RegExp(regexMatch[1], regexMatch[2]);
}
return !!value1.toString().match(regex);
},
};
function SetXML(config) {
RED.nodes.createNode(this, config);
this.matches = config.matches;
const node = this;
let allConditionsMatch = true;
this.on('input', async (msg, send, done) => {
const { payload } = msg;
const { call } = payload;
if (!(call && call.call_uuid)) {
this.error(`'set-xml' called on non-existent call.`);
return;
}
try {
const calls = await callsDb.fetch(call.call_uuid);
if (calls && calls[0]) {
msg.payload.call = calls[0];
}
} catch (err) {
console.error('An error has occured.', payload, err);
}
for (const match of this.matches) {
const conditions = match.conditions;
const properties = match.properties;
let allCaseConditionsMatch = true;
for (const condition of conditions) {
const {
property,
propertyValueExp,
operation,
value,
xml,
xmlValueType
} = condition;
if (property === 'always_match') {
// already updating the script as it always matches
try {
const xmlOutput = RED.util.evaluateNodeProperty(xml, xmlValueType, node, msg);
const scriptItem = await parser.parseStringPromise(`<root>${xmlOutput}</root>`);
msg.payload.script.push(scriptItem);
} catch (err) {
this.error('Error dealing with the XML preparation.');
}
continue;
}
const operationFunc = operations[operation];
const isPropertyCustomString = property === 'custom_string';
const data = (() => {
if (isPropertyCustomString) {
try {
return jsonata(propertyValueExp).evaluate(msg);
} catch (err) {
console.error(
'An error has occured with jsonata.',
payload,
err
);
return '';
}
}
return msg.payload.call[property];
})();
const operationResult = operationFunc(data, value);
if (operationResult === false) {
allCaseConditionsMatch = false;
}
}
if (allCaseConditionsMatch) {
properties.forEach((property) => {
const { key, value } = property;
msg.payload.call.custom[key] = value;
});
if (properties.length) {
await callsDb.update(call.call_uuid, msg.payload.call);
}
} else {
allConditionsMatch = false;
}
}
if (allConditionsMatch) {
send(msg);
} else {
send(null);
}
done();
});
}
RED.nodes.registerType('set-xml', SetXML);
};