mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge e770830947 into a2430b772b
				
					
				
			This commit is contained in:
		@@ -1,7 +1,11 @@
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="range">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-sign-in"></i> <span data-i18n="common.label.propertyIn"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-property" style="width:calc(70% - 1px)"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
@@ -31,8 +35,8 @@
 | 
			
		||||
    </div>
 | 
			
		||||
    <br/>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
        <label for="node-input-propertyOut"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-propertyOut" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-tips" id="node-tip"><span data-i18n="range.tip"></span></div>
 | 
			
		||||
</script>
 | 
			
		||||
@@ -57,9 +61,13 @@
 | 
			
		||||
            action: {value:"scale"},
 | 
			
		||||
            round: {value:false},
 | 
			
		||||
            property: {value:"payload",required:true,
 | 
			
		||||
                       label:RED._("node-red:common.label.property"),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyIn"),
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowBlank: true })
 | 
			
		||||
                    },
 | 
			
		||||
            propertyOut: {value:"payload",required:true,
 | 
			
		||||
                    validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
 | 
			
		||||
                    label:RED._("node-red:common.label.propertyOut")},
 | 
			
		||||
 | 
			
		||||
            name: {value:""}
 | 
			
		||||
        },
 | 
			
		||||
        inputs: 1,
 | 
			
		||||
@@ -77,6 +85,10 @@
 | 
			
		||||
                $("#node-input-property").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-property").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            if (this.propertyOut === undefined) {
 | 
			
		||||
                $("#node-input-propertyOut").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-propertyOut").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
 | 
			
		||||
module.exports = function(RED) {
 | 
			
		||||
    "use strict";
 | 
			
		||||
    const { getMessagePropertySafe } = require('../utils.js')(RED)
 | 
			
		||||
    function RangeNode(n) {
 | 
			
		||||
        RED.nodes.createNode(this, n);
 | 
			
		||||
        this.action = n.action;
 | 
			
		||||
@@ -25,10 +26,11 @@ module.exports = function(RED) {
 | 
			
		||||
        this.minout = Number(n.minout);
 | 
			
		||||
        this.maxout = Number(n.maxout);
 | 
			
		||||
        this.property = n.property||"payload";
 | 
			
		||||
        this.propertyOut = n.propertyOut||this.property;
 | 
			
		||||
        var node = this;
 | 
			
		||||
 | 
			
		||||
        this.on('input', function (msg, send, done) {
 | 
			
		||||
            var value = RED.util.getMessageProperty(msg,node.property);
 | 
			
		||||
            var value = getMessagePropertySafe(msg, node.property);
 | 
			
		||||
            if (value !== undefined) {
 | 
			
		||||
                var n = Number(value);
 | 
			
		||||
                if (!isNaN(n)) {
 | 
			
		||||
@@ -46,7 +48,7 @@ module.exports = function(RED) {
 | 
			
		||||
                    }
 | 
			
		||||
                    value = ((n - node.minin) / (node.maxin - node.minin) * (node.maxout - node.minout)) + node.minout;
 | 
			
		||||
                    if (node.round) { value = Math.round(value); }
 | 
			
		||||
                    RED.util.setMessageProperty(msg,node.property,value);
 | 
			
		||||
                    RED.util.setMessageProperty(msg,node.propertyOut,value);
 | 
			
		||||
                    send(msg);
 | 
			
		||||
                }
 | 
			
		||||
                else { node.log(RED._("range.errors.notnumber")+": "+value); }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,11 +4,6 @@
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <div style="display: inline-block; width: calc(100% - 105px)"><input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-field"><i class="fa fa-ellipsis-h"></i> <span data-i18n="template.label.property"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-field" placeholder="payload" style="width:250px;">
 | 
			
		||||
        <input type="hidden" id="node-input-fieldType">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row" style="position: relative; margin-bottom: 0px;">
 | 
			
		||||
        <label for="node-input-template"><i class="fa fa-file-code-o"></i> <span data-i18n="template.label.template"></span></label>
 | 
			
		||||
        <input type="hidden" id="node-input-template" autofocus="autofocus">
 | 
			
		||||
@@ -41,14 +36,18 @@
 | 
			
		||||
        </select>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-output"><i class="fa fa-long-arrow-right"></i> <span data-i18n="template.label.output"></span></label>
 | 
			
		||||
        <label for="node-input-output"><i class="fa fa-sign-out"></i> <span data-i18n="template.label.output"></span></label>
 | 
			
		||||
        <select id="node-input-output" style="width:180px;">
 | 
			
		||||
            <option value="str" data-i18n="template.label.plain"></option>
 | 
			
		||||
            <option value="json" data-i18n="template.label.json"></option>
 | 
			
		||||
            <option value="yaml" data-i18n="template.label.yaml"></option>
 | 
			
		||||
        </select>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-field"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-field" placeholder="payload" style="width:250px;">
 | 
			
		||||
        <input type="hidden" id="node-input-fieldType">
 | 
			
		||||
    </div>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,16 @@
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="http request">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-sign-in"></i> <span data-i18n="common.label.propertyIn"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-property" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
 | 
			
		||||
        <select type="text" id="node-input-method" style="width:70%;">
 | 
			
		||||
@@ -98,7 +108,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label>
 | 
			
		||||
        <label for="node-input-ret"><i class="fa fa-sign-out"></i> <span data-i18n="httpin.label.return"></span></label>
 | 
			
		||||
        <select type="text" id="node-input-ret" style="width:70%;">
 | 
			
		||||
        <option value="txt" data-i18n="httpin.utf8"></option>
 | 
			
		||||
        <option value="bin" data-i18n="httpin.binary"></option>
 | 
			
		||||
@@ -107,7 +117,10 @@
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="form-row form-tips" id="tip-json" hidden><span data-i18n="httpin.tip.req"></span></div>
 | 
			
		||||
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-propertyOut"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-propertyOut" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row" style="margin-bottom:0;">
 | 
			
		||||
        <label><i class="fa fa-list"></i> <span data-i18n="httpin.label.headers"></span></label>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -115,10 +128,7 @@
 | 
			
		||||
        <ol id="node-input-headers-container"></ol>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
@@ -235,7 +245,13 @@
 | 
			
		||||
            insecureHTTPParser: {value: false},
 | 
			
		||||
            authType: {value: ""},
 | 
			
		||||
            senderr: {value: false},
 | 
			
		||||
            headers: { value: [] }
 | 
			
		||||
            headers: { value: [] },
 | 
			
		||||
            property: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true }),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyIn")},
 | 
			
		||||
            propertyOut: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyOut")}
 | 
			
		||||
        },
 | 
			
		||||
        credentials: {
 | 
			
		||||
            user: {type:"text"},
 | 
			
		||||
@@ -426,6 +442,15 @@
 | 
			
		||||
                    headerList.editableList('addItem', node.headers[index]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (this.property === undefined) {
 | 
			
		||||
                $("#node-input-property").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-property").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            if (this.propertyOut === undefined) {
 | 
			
		||||
                $("#node-input-propertyOut").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-propertyOut").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
 | 
			
		||||
        },
 | 
			
		||||
        oneditsave: function() {
 | 
			
		||||
            if (!$("#node-input-usetls").is(':checked')) {
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ module.exports = async function(RED) {
 | 
			
		||||
    var querystring = require("querystring");
 | 
			
		||||
    var cookie = require("cookie");
 | 
			
		||||
    var hashSum = require("hash-sum");
 | 
			
		||||
 | 
			
		||||
    const { getMessagePropertySafe } = require('../utils.js')(RED)
 | 
			
		||||
 | 
			
		||||
    // Cache a reference to the existing https.request function
 | 
			
		||||
    // so we can compare later to see if an old agent-base instance
 | 
			
		||||
@@ -69,6 +69,8 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
        RED.nodes.createNode(this,n);
 | 
			
		||||
        checkNodeAgentPatch();
 | 
			
		||||
        const node = this;
 | 
			
		||||
        node.property = n.property||"payload";
 | 
			
		||||
        node.propertyOut = n.propertyOut||node.property;
 | 
			
		||||
        const nodeUrl = n.url;
 | 
			
		||||
        const isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1;
 | 
			
		||||
        const nodeMethod = n.method || "GET";
 | 
			
		||||
@@ -445,14 +447,14 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            var payload = null;
 | 
			
		||||
            const value = getMessagePropertySafe(msg, node.property)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (method !== 'GET' && method !== 'HEAD' && typeof msg.payload !== "undefined") {
 | 
			
		||||
                if (opts.headers['content-type'] == 'multipart/form-data' && typeof msg.payload === "object") {
 | 
			
		||||
            if (method !== 'GET' && method !== 'HEAD' && typeof value !== "undefined") {
 | 
			
		||||
                if (opts.headers['content-type'] == 'multipart/form-data' && typeof value === "object") {
 | 
			
		||||
                    let formData = new FormData();
 | 
			
		||||
                    for (var opt in msg.payload) {
 | 
			
		||||
                        if (msg.payload.hasOwnProperty(opt)) {
 | 
			
		||||
                            var val = msg.payload[opt];
 | 
			
		||||
                    for (var opt in value) {
 | 
			
		||||
                        if (value.hasOwnProperty(opt)) {
 | 
			
		||||
                            var val = value[opt];
 | 
			
		||||
                            if (val !== undefined && val !== null) {
 | 
			
		||||
                                if (typeof val === 'string' || Buffer.isBuffer(val)) {
 | 
			
		||||
                                    formData.append(opt, val);
 | 
			
		||||
@@ -469,15 +471,15 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
                    delete opts.headers['content-type'];
 | 
			
		||||
                    opts.body = formData;
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
 | 
			
		||||
                        payload = msg.payload;
 | 
			
		||||
                    } else if (typeof msg.payload == "number") {
 | 
			
		||||
                        payload = msg.payload+"";
 | 
			
		||||
                    if (typeof value === "string" || Buffer.isBuffer(value)) {
 | 
			
		||||
                        payload = value;
 | 
			
		||||
                    } else if (typeof value == "number") {
 | 
			
		||||
                        payload = value + "";
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') {
 | 
			
		||||
                            payload = querystring.stringify(msg.payload);
 | 
			
		||||
                            payload = querystring.stringify(value);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            payload = JSON.stringify(msg.payload);
 | 
			
		||||
                            payload = JSON.stringify(value);
 | 
			
		||||
                            if (opts.headers['content-type'] == null) {
 | 
			
		||||
                                opts.headers[ctSet] = "application/json";
 | 
			
		||||
                            }
 | 
			
		||||
@@ -495,13 +497,13 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (method == 'GET' && typeof msg.payload !== "undefined" && paytoqs) {
 | 
			
		||||
                if (typeof msg.payload === "object") {
 | 
			
		||||
            if (method == 'GET' && typeof value !== "undefined" && paytoqs) {
 | 
			
		||||
                if (typeof value === "object") {
 | 
			
		||||
                    try {
 | 
			
		||||
                        if (url.indexOf("?") !== -1) {
 | 
			
		||||
                            url += (url.endsWith("?")?"":"&") + querystring.stringify(msg.payload);
 | 
			
		||||
                            url += (url.endsWith("?")?"":"&") + querystring.stringify(value);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            url += "?" + querystring.stringify(msg.payload);
 | 
			
		||||
                            url += "?" + querystring.stringify(value);
 | 
			
		||||
                        }
 | 
			
		||||
                    } catch(err) {
 | 
			
		||||
 | 
			
		||||
@@ -515,14 +517,14 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
                    nodeDone();
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            } else if ( method == "GET" && typeof msg.payload !== "undefined" && paytobody) {
 | 
			
		||||
            } else if ( method == "GET" && typeof value !== "undefined" && paytobody) {
 | 
			
		||||
                opts.allowGetBody = true;
 | 
			
		||||
                if (typeof msg.payload === "object") {
 | 
			
		||||
                    opts.body = JSON.stringify(msg.payload);
 | 
			
		||||
                } else if (typeof msg.payload == "number") {
 | 
			
		||||
                    opts.body = msg.payload+"";
 | 
			
		||||
                } else if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
 | 
			
		||||
                    opts.body = msg.payload;
 | 
			
		||||
                if (typeof value === "object") {
 | 
			
		||||
                    opts.body = JSON.stringify(value);
 | 
			
		||||
                } else if (typeof value == "number") {
 | 
			
		||||
                    opts.body = value + "";
 | 
			
		||||
                } else if (typeof value === "string" || Buffer.isBuffer(value)) {
 | 
			
		||||
                    opts.body = value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -603,7 +605,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
                msg.statusCode = res.statusCode;
 | 
			
		||||
                msg.headers = res.headers;
 | 
			
		||||
                msg.responseUrl = res.url;
 | 
			
		||||
                msg.payload = res.body;
 | 
			
		||||
                let result = res.body;
 | 
			
		||||
                msg.redirectList = redirectList;
 | 
			
		||||
                msg.retry = 0;
 | 
			
		||||
 | 
			
		||||
@@ -628,14 +630,15 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
 | 
			
		||||
                // Convert the payload to the required return type
 | 
			
		||||
                if (node.ret !== "bin") {
 | 
			
		||||
                    msg.payload = msg.payload.toString('utf8'); // txt
 | 
			
		||||
                    result = result.toString('utf8'); // txt
 | 
			
		||||
 | 
			
		||||
                    if (node.ret === "obj") {
 | 
			
		||||
                        if (msg.statusCode == 204){msg.payload= "{}"};
 | 
			
		||||
                        try { msg.payload = JSON.parse(msg.payload); } // obj
 | 
			
		||||
                        if (msg.statusCode == 204){result= "{}"};
 | 
			
		||||
                        try { result = JSON.parse(result); } // obj
 | 
			
		||||
                        catch(e) { node.warn(RED._("httpin.errors.json-error")); }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                RED.util.setMessageProperty(msg, node.propertyOut, result)
 | 
			
		||||
                node.status({});
 | 
			
		||||
                nodeSend(msg);
 | 
			
		||||
                nodeDone();
 | 
			
		||||
@@ -653,7 +656,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
 | 
			
		||||
                    node.error(err,msg);
 | 
			
		||||
                    node.status({fill:"red", shape:"ring", text:err.code});
 | 
			
		||||
                }
 | 
			
		||||
                msg.payload = err.toString() + " : " + url;
 | 
			
		||||
                RED.util.setMessageProperty(msg, node.propertyOut, err.toString() + " : " + url)
 | 
			
		||||
                msg.statusCode = err.code || (err.response?err.response.statusCode:undefined);
 | 
			
		||||
                if (node.metric() && timingLog) {
 | 
			
		||||
                    emitTimingMetricLog(err.timings, msg);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,13 @@
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="csv">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-sign-in"></i> <span data-i18n="common.label.propertyIn"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-property" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-temp"><i class="fa fa-list"></i> <span data-i18n="csv.label.columns"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-temp" data-i18n="[placeholder]csv.placeholder.columns">
 | 
			
		||||
@@ -32,8 +40,8 @@
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
        <label for="node-input-propertyOut"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-propertyOut" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr align="middle"/>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
@@ -102,7 +110,13 @@
 | 
			
		||||
            skip: {value:"0"},
 | 
			
		||||
            strings: {value:true},
 | 
			
		||||
            include_empty_strings: {value:""},
 | 
			
		||||
            include_null_values: {value:""}
 | 
			
		||||
            include_null_values: {value:""},
 | 
			
		||||
            property: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true }),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyIn")},
 | 
			
		||||
            propertyOut: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyOut")}
 | 
			
		||||
        },
 | 
			
		||||
        inputs:1,
 | 
			
		||||
        outputs:1,
 | 
			
		||||
@@ -114,6 +128,15 @@
 | 
			
		||||
            return this.name?"node_label_italic":"";
 | 
			
		||||
        },
 | 
			
		||||
        oneditprepare: function() {
 | 
			
		||||
            if (this.property === undefined) {
 | 
			
		||||
                $("#node-input-property").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            if (this.property === undefined) {
 | 
			
		||||
                $("#node-input-propertyOut").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-property").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            $("#node-input-propertyOut").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
 | 
			
		||||
            if (this.hdrout === false) { this.hdrout = "none"; $("#node-input-hdrout").val("none"); }
 | 
			
		||||
            if (this.hdrout === true) { this.hdrout = "all"; $("#node-input-hdrout").val("all");}
 | 
			
		||||
            if (this.strings === undefined) { this.strings = true; $("#node-input-strings").prop('checked', true); }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,11 @@
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
module.exports = function(RED) {
 | 
			
		||||
    const csv = require('./lib/csv')
 | 
			
		||||
 | 
			
		||||
    "use strict";
 | 
			
		||||
 | 
			
		||||
    const csv = require('./lib/csv')
 | 
			
		||||
    const { getMessagePropertySafe } = require('../utils.js')(RED)
 | 
			
		||||
 | 
			
		||||
    function CSVNode(n) {
 | 
			
		||||
        RED.nodes.createNode(this,n)
 | 
			
		||||
        const node = this
 | 
			
		||||
@@ -26,6 +28,9 @@ module.exports = function(RED) {
 | 
			
		||||
 | 
			
		||||
        node.status({}) // clear status
 | 
			
		||||
 | 
			
		||||
        node.property = n.property||"payload";
 | 
			
		||||
        node.propertyOut = n.propertyOut||node.property;
 | 
			
		||||
 | 
			
		||||
        if (legacyMode) {
 | 
			
		||||
            this.template = (n.temp || "");
 | 
			
		||||
            this.sep = (n.sep || ',').replace(/\\t/g,"\t").replace(/\\n/g,"\n").replace(/\\r/g,"\r");
 | 
			
		||||
@@ -66,43 +71,44 @@ module.exports = function(RED) {
 | 
			
		||||
                if (msg.hasOwnProperty("reset")) {
 | 
			
		||||
                    node.hdrSent = false;
 | 
			
		||||
                }
 | 
			
		||||
                if (msg.hasOwnProperty("payload")) {
 | 
			
		||||
                    if (typeof msg.payload == "object") { // convert object to CSV string
 | 
			
		||||
                let inputData = getMessagePropertySafe(msg, node.property)
 | 
			
		||||
                if (typeof inputData !== "undefined") {
 | 
			
		||||
                    if (typeof inputData == "object") { // convert object to CSV string
 | 
			
		||||
                        try {
 | 
			
		||||
                            if (!(notemplate && (msg.hasOwnProperty("parts") && msg.parts.hasOwnProperty("index") && msg.parts.index > 0))) {
 | 
			
		||||
                                template = clean(node.template);
 | 
			
		||||
                            }
 | 
			
		||||
                            const ou = [];
 | 
			
		||||
                            if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
 | 
			
		||||
                            if (!Array.isArray(inputData)) { inputData = [ inputData ]; }
 | 
			
		||||
                            if (node.hdrout !== "none" && node.hdrSent === false) {
 | 
			
		||||
                                if ((template.length === 1) && (template[0] === '')) {
 | 
			
		||||
                                    if (msg.hasOwnProperty("columns")) {
 | 
			
		||||
                                        template = clean(msg.columns || "",",");
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else {
 | 
			
		||||
                                        template = Object.keys(msg.payload[0]);
 | 
			
		||||
                                        template = Object.keys(inputData[0]);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                ou.push(template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep));
 | 
			
		||||
                                if (node.hdrout === "once") { node.hdrSent = true; }
 | 
			
		||||
                            }
 | 
			
		||||
                            for (var s = 0; s < msg.payload.length; s++) {
 | 
			
		||||
                                if ((Array.isArray(msg.payload[s])) || (typeof msg.payload[s] !== "object")) {
 | 
			
		||||
                                    if (typeof msg.payload[s] !== "object") { msg.payload = [ msg.payload ]; }
 | 
			
		||||
                                    for (var t = 0; t < msg.payload[s].length; t++) {
 | 
			
		||||
                                        if (msg.payload[s][t] === undefined) { msg.payload[s][t] = ""; }
 | 
			
		||||
                                        if (msg.payload[s][t].toString().indexOf(node.quo) !== -1) { // add double quotes if any quotes
 | 
			
		||||
                                            msg.payload[s][t] = msg.payload[s][t].toString().replace(/"/g, '""');
 | 
			
		||||
                                            msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
 | 
			
		||||
                            for (var s = 0; s < inputData.length; s++) {
 | 
			
		||||
                                if ((Array.isArray(inputData[s])) || (typeof inputData[s] !== "object")) {
 | 
			
		||||
                                    if (typeof inputData[s] !== "object") { inputData = [ inputData ]; }
 | 
			
		||||
                                    for (var t = 0; t < inputData[s].length; t++) {
 | 
			
		||||
                                        if (inputData[s][t] === undefined) { inputData[s][t] = ""; }
 | 
			
		||||
                                        if (inputData[s][t].toString().indexOf(node.quo) !== -1) { // add double quotes if any quotes
 | 
			
		||||
                                            inputData[s][t] = inputData[s][t].toString().replace(/"/g, '""');
 | 
			
		||||
                                            inputData[s][t] = node.quo + inputData[s][t].toString() + node.quo;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        else if (msg.payload[s][t].toString().indexOf(node.sep) !== -1) { // add quotes if any "commas"
 | 
			
		||||
                                            msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
 | 
			
		||||
                                        else if (inputData[s][t].toString().indexOf(node.sep) !== -1) { // add quotes if any "commas"
 | 
			
		||||
                                            inputData[s][t] = node.quo + inputData[s][t].toString() + node.quo;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        else if (msg.payload[s][t].toString().indexOf("\n") !== -1) { // add quotes if any "\n"
 | 
			
		||||
                                            msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
 | 
			
		||||
                                        else if (inputData[s][t].toString().indexOf("\n") !== -1) { // add quotes if any "\n"
 | 
			
		||||
                                            inputData[s][t] = node.quo + inputData[s][t].toString() + node.quo;
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                    ou.push(msg.payload[s].join(node.sep));
 | 
			
		||||
                                    ou.push(inputData[s].join(node.sep));
 | 
			
		||||
                                }
 | 
			
		||||
                                else {
 | 
			
		||||
                                    if ((template.length === 1) && (template[0] === '') && (msg.hasOwnProperty("columns"))) {
 | 
			
		||||
@@ -115,16 +121,16 @@ module.exports = function(RED) {
 | 
			
		||||
                                            tmpwarn = false;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        const row = [];
 | 
			
		||||
                                        for (var p in msg.payload[0]) {
 | 
			
		||||
                                        for (var p in inputData[0]) {
 | 
			
		||||
                                            /* istanbul ignore else */
 | 
			
		||||
                                            if (msg.payload[s].hasOwnProperty(p)) {
 | 
			
		||||
                                            if (inputData[s].hasOwnProperty(p)) {
 | 
			
		||||
                                                /* istanbul ignore else */
 | 
			
		||||
                                                if (typeof msg.payload[s][p] !== "object") {
 | 
			
		||||
                                                if (typeof inputData[s][p] !== "object") {
 | 
			
		||||
                                                // Fix to honour include null values flag
 | 
			
		||||
                                                //if (typeof msg.payload[s][p] !== "object" || (node.include_null_values === true && msg.payload[s][p] === null)) {
 | 
			
		||||
                                                //if (typeof inputData[s][p] !== "object" || (node.include_null_values === true && inputData[s][p] === null)) {
 | 
			
		||||
                                                    var q = "";
 | 
			
		||||
                                                    if (msg.payload[s][p] !== undefined) {
 | 
			
		||||
                                                        q += msg.payload[s][p];
 | 
			
		||||
                                                    if (inputData[s][p] !== undefined) {
 | 
			
		||||
                                                        q += inputData[s][p];
 | 
			
		||||
                                                    }
 | 
			
		||||
                                                    if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
 | 
			
		||||
                                                        q = q.replace(/"/g, '""');
 | 
			
		||||
@@ -149,7 +155,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                                var tt = template[t];
 | 
			
		||||
                                                if (template[t].indexOf('"') >=0 ) { tt = "'"+tt+"'"; }
 | 
			
		||||
                                                else { tt = '"'+tt+'"'; }
 | 
			
		||||
                                                var p = RED.util.getMessageProperty(msg,'payload["'+s+'"]['+tt+']');
 | 
			
		||||
                                                var p = RED.util.getMessageProperty(inputData[s] || {}, tt);
 | 
			
		||||
                                                /* istanbul ignore else */
 | 
			
		||||
                                                if (p === undefined) { p = ""; }
 | 
			
		||||
                                                // fix to honour include null values flag
 | 
			
		||||
@@ -170,16 +176,17 @@ module.exports = function(RED) {
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            // join lines, don't forget to add the last new line
 | 
			
		||||
                            msg.payload = ou.join(node.ret) + node.ret;
 | 
			
		||||
                            inputData = ou.join(node.ret) + node.ret;
 | 
			
		||||
                            RED.util.setMessageProperty(msg, node.propertyOut, inputData)
 | 
			
		||||
                            msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
 | 
			
		||||
                            if (msg.payload !== '') {
 | 
			
		||||
                            if (inputData !== '') {
 | 
			
		||||
                                send(msg);
 | 
			
		||||
                            }
 | 
			
		||||
                            done();
 | 
			
		||||
                        }
 | 
			
		||||
                        catch(e) { done(e); }
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (typeof msg.payload == "string") { // convert CSV string to object
 | 
			
		||||
                    else if (typeof inputData == "string") { // convert CSV string to object
 | 
			
		||||
                        try {
 | 
			
		||||
                            var f = true; // flag to indicate if inside or outside a pair of quotes true = outside.
 | 
			
		||||
                            var j = 0; // pointer into array of template items
 | 
			
		||||
@@ -188,7 +195,7 @@ module.exports = function(RED) {
 | 
			
		||||
                            var a = []; // output array is needed for multiline option
 | 
			
		||||
                            var first = true; // is this the first line
 | 
			
		||||
                            var last = false;
 | 
			
		||||
                            var line = msg.payload;
 | 
			
		||||
                            var line = inputData;
 | 
			
		||||
                            var linecount = 0;
 | 
			
		||||
                            var tmp = "";
 | 
			
		||||
                            var has_parts = msg.hasOwnProperty("parts");
 | 
			
		||||
@@ -282,13 +289,13 @@ module.exports = function(RED) {
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (node.multi !== "one") {
 | 
			
		||||
                                msg.payload = a;
 | 
			
		||||
                                RED.util.setMessageProperty(msg, node.propertyOut, a);
 | 
			
		||||
                                if (has_parts && nocr <= 1) {
 | 
			
		||||
                                    if (JSON.stringify(o) !== "{}") {
 | 
			
		||||
                                        node.store.push(o);
 | 
			
		||||
                                    }
 | 
			
		||||
                                    if (msg.parts.index + 1 === msg.parts.count) {
 | 
			
		||||
                                        msg.payload = node.store;
 | 
			
		||||
                                        RED.util.setMessageProperty(msg, node.propertyOut, node.store);
 | 
			
		||||
                                        msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
 | 
			
		||||
                                        delete msg.parts;
 | 
			
		||||
                                        send(msg);
 | 
			
		||||
@@ -305,7 +312,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                for (var i = 0; i < len; i++) {
 | 
			
		||||
                                    var newMessage = RED.util.cloneMessage(msg);
 | 
			
		||||
                                    newMessage.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
 | 
			
		||||
                                    newMessage.payload = a[i];
 | 
			
		||||
                                    RED.util.setMessageProperty(newMessage, node.propertyOut, a[i])
 | 
			
		||||
                                    if (!has_parts) {
 | 
			
		||||
                                        newMessage.parts = {
 | 
			
		||||
                                            id: msg._msgid,
 | 
			
		||||
@@ -411,8 +418,8 @@ module.exports = function(RED) {
 | 
			
		||||
                if (msg.hasOwnProperty("reset")) {
 | 
			
		||||
                    node.hdrSent = false
 | 
			
		||||
                }
 | 
			
		||||
                if (msg.hasOwnProperty("payload")) {
 | 
			
		||||
                    let inputData = msg.payload
 | 
			
		||||
                let inputData = getMessagePropertySafe(msg, node.property)
 | 
			
		||||
                if (typeof inputData !== "undefined") {
 | 
			
		||||
                    if (typeof inputData == "object") { // convert object to CSV string
 | 
			
		||||
                        try {
 | 
			
		||||
                            // first determine the payload kind. Array or objects? Array of primitives? Array of arrays? Just an object?
 | 
			
		||||
@@ -517,9 +524,10 @@ module.exports = function(RED) {
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            // join lines, don't forget to add the last new line
 | 
			
		||||
                            msg.payload = stringBuilder.join(node.ret) + node.ret
 | 
			
		||||
                            const result = stringBuilder.join(node.ret) + node.ret
 | 
			
		||||
                            RED.util.setMessageProperty(msg, node.propertyOut, result)
 | 
			
		||||
                            msg.columns = templateArrayToColumnString(template)
 | 
			
		||||
                            if (msg.payload !== '') { send(msg) }
 | 
			
		||||
                            if (result !== '') { send(msg) }
 | 
			
		||||
                            done()
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (e) { 
 | 
			
		||||
@@ -614,7 +622,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                        node.store.push(...data)
 | 
			
		||||
                                    }
 | 
			
		||||
                                    if (msg.parts.index + 1 === msg.parts.count) {
 | 
			
		||||
                                        msg.payload = node.store
 | 
			
		||||
                                        RED.util.setMessageProperty(msg, node.propertyOut, node.store)
 | 
			
		||||
                                        msg.columns = csvParseResult.header
 | 
			
		||||
                                        // msg._mode = 'RFC4180 mode'
 | 
			
		||||
                                        delete msg.parts
 | 
			
		||||
@@ -625,7 +633,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                else {
 | 
			
		||||
                                    msg.columns = csvParseResult.header
 | 
			
		||||
                                    // msg._mode = 'RFC4180 mode'
 | 
			
		||||
                                    msg.payload = data
 | 
			
		||||
                                    RED.util.setMessageProperty(msg, node.propertyOut, data)
 | 
			
		||||
                                    send(msg); // finally send the array
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
@@ -634,7 +642,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                for (let row = 0; row < len; row++) {
 | 
			
		||||
                                    const newMessage = RED.util.cloneMessage(msg)
 | 
			
		||||
                                    newMessage.columns = csvParseResult.header
 | 
			
		||||
                                    newMessage.payload = data[row]
 | 
			
		||||
                                    RED.util.setMessageProperty(newMessage, node.propertyOut, data[row])
 | 
			
		||||
                                    if (!has_parts) {
 | 
			
		||||
                                        newMessage.parts = {
 | 
			
		||||
                                            id: msg._msgid,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,13 @@
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="json">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-sign-in"></i> <span data-i18n="common.label.propertyIn"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-property" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-action"><i class="fa fa-dot-circle-o"></i> <span data-i18n="json.label.action"></span></label>
 | 
			
		||||
        <select style="width:70%" id="node-input-action">
 | 
			
		||||
@@ -9,12 +17,8 @@
 | 
			
		||||
        </select>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="json.label.property"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-property" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
        <label for="node-input-propertyOut"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-propertyOut" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr align="middle"/>
 | 
			
		||||
    <div class="form-row node-json-to-json-options">
 | 
			
		||||
@@ -33,7 +37,10 @@
 | 
			
		||||
            name: {value:""},
 | 
			
		||||
            property: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
 | 
			
		||||
                       label:RED._("node-red:json.label.property")},
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyIn")},
 | 
			
		||||
            propertyOut: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyOut")},
 | 
			
		||||
            action: {value:""},
 | 
			
		||||
            pretty: {value:false}
 | 
			
		||||
        },
 | 
			
		||||
@@ -50,7 +57,11 @@
 | 
			
		||||
            if (this.property === undefined) {
 | 
			
		||||
                $("#node-input-property").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            if (this.propertyOut === undefined) {
 | 
			
		||||
                $("#node-input-propertyOut").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-property").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            $("#node-input-propertyOut").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            $("#node-input-action").on("change", function() {
 | 
			
		||||
                if (this.value === "" || this.value === "str") {
 | 
			
		||||
                    $(".node-json-to-json-options").show();
 | 
			
		||||
 
 | 
			
		||||
@@ -19,12 +19,14 @@ module.exports = function(RED) {
 | 
			
		||||
    const Ajv = require('ajv');
 | 
			
		||||
    const ajv = new Ajv({allErrors: true});
 | 
			
		||||
    ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'));
 | 
			
		||||
    const { getMessagePropertySafe } = require('../utils.js')(RED)
 | 
			
		||||
 | 
			
		||||
    function JSONNode(n) {
 | 
			
		||||
        RED.nodes.createNode(this,n);
 | 
			
		||||
        this.indent = n.pretty ? 4 : 0;
 | 
			
		||||
        this.action = n.action||"";
 | 
			
		||||
        this.property = n.property||"payload";
 | 
			
		||||
        this.propertyOut = n.propertyOut||this.property;
 | 
			
		||||
        this.schema = null;
 | 
			
		||||
        this.compiledSchema = null;
 | 
			
		||||
 | 
			
		||||
@@ -47,7 +49,7 @@ module.exports = function(RED) {
 | 
			
		||||
                }
 | 
			
		||||
                validate = true;
 | 
			
		||||
            }
 | 
			
		||||
            var value = RED.util.getMessageProperty(msg,node.property);
 | 
			
		||||
            var value = getMessagePropertySafe(msg,node.property);
 | 
			
		||||
            if (value !== undefined) {
 | 
			
		||||
                if (typeof value === "string" || Buffer.isBuffer(value)) {
 | 
			
		||||
                    // if (Buffer.isBuffer(value) && node.action !== "obj") {
 | 
			
		||||
@@ -56,7 +58,7 @@ module.exports = function(RED) {
 | 
			
		||||
                    // else
 | 
			
		||||
                    if (node.action === "" || node.action === "obj") {
 | 
			
		||||
                        try {
 | 
			
		||||
                            RED.util.setMessageProperty(msg,node.property,JSON.parse(value));
 | 
			
		||||
                            RED.util.setMessageProperty(msg,node.propertyOut,JSON.parse(value));
 | 
			
		||||
                            if (validate) {
 | 
			
		||||
                                if (this.compiledSchema(msg[node.property])) {
 | 
			
		||||
                                    delete msg.schema;
 | 
			
		||||
@@ -95,7 +97,7 @@ module.exports = function(RED) {
 | 
			
		||||
                            try {
 | 
			
		||||
                                if (validate) {
 | 
			
		||||
                                    if (this.compiledSchema(value)) {
 | 
			
		||||
                                        RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
 | 
			
		||||
                                        RED.util.setMessageProperty(msg,node.propertyOut,JSON.stringify(value,null,node.indent));
 | 
			
		||||
                                        delete msg.schema;
 | 
			
		||||
                                        send(msg);
 | 
			
		||||
                                        done();
 | 
			
		||||
@@ -104,7 +106,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                        done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
 | 
			
		||||
                                    }
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
 | 
			
		||||
                                    RED.util.setMessageProperty(msg,node.propertyOut,JSON.stringify(value,null,node.indent));
 | 
			
		||||
                                    send(msg);
 | 
			
		||||
                                    done();
 | 
			
		||||
                                }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,16 @@
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="xml">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-sign-in"></i> <span data-i18n="common.label.propertyIn"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-property" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
        <label for="node-input-propertyOut"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-propertyOut" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr align="middle"/>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
@@ -27,7 +31,11 @@
 | 
			
		||||
        defaults: {
 | 
			
		||||
            name: {value:""},
 | 
			
		||||
            property: {value:"payload",required:true,
 | 
			
		||||
                       label:RED._("node-red:common.label.property"),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyIn"),
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true })},
 | 
			
		||||
            attr: {value:""},
 | 
			
		||||
            propertyOut: {value:"payload",required:true,
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyOut"),
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true })},
 | 
			
		||||
            attr: {value:""},
 | 
			
		||||
            chr: {value:""}
 | 
			
		||||
@@ -45,7 +53,11 @@
 | 
			
		||||
            if (this.property === undefined) {
 | 
			
		||||
                $("#node-input-property").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            if (this.propertyOut === undefined) {
 | 
			
		||||
                $("#node-input-propertyOut").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-property").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            $("#node-input-propertyOut").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,15 +3,17 @@ module.exports = function(RED) {
 | 
			
		||||
    "use strict";
 | 
			
		||||
    var xml2js = require('xml2js');
 | 
			
		||||
    var parseString = xml2js.parseString;
 | 
			
		||||
    const { getMessagePropertySafe } = require('../utils.js')(RED)
 | 
			
		||||
 | 
			
		||||
    function XMLNode(n) {
 | 
			
		||||
        RED.nodes.createNode(this,n);
 | 
			
		||||
        this.attrkey = n.attr;
 | 
			
		||||
        this.charkey = n.chr;
 | 
			
		||||
        this.property = n.property||"payload";
 | 
			
		||||
        this.propertyOut = n.propertyOut||this.property;
 | 
			
		||||
        var node = this;
 | 
			
		||||
        this.on("input", function(msg,send,done) {
 | 
			
		||||
            var value = RED.util.getMessageProperty(msg,node.property);
 | 
			
		||||
            var value = getMessagePropertySafe(msg,node.property);
 | 
			
		||||
            if (value !== undefined) {
 | 
			
		||||
                var options;
 | 
			
		||||
                if (typeof value === "object") {
 | 
			
		||||
@@ -20,7 +22,7 @@ module.exports = function(RED) {
 | 
			
		||||
                    options.async = false;
 | 
			
		||||
                    var builder = new xml2js.Builder(options);
 | 
			
		||||
                    value = builder.buildObject(value, options);
 | 
			
		||||
                    RED.util.setMessageProperty(msg,node.property,value);
 | 
			
		||||
                    RED.util.setMessageProperty(msg,node.propertyOut,value);
 | 
			
		||||
                    send(msg);
 | 
			
		||||
                    done();
 | 
			
		||||
                }
 | 
			
		||||
@@ -33,7 +35,7 @@ module.exports = function(RED) {
 | 
			
		||||
                    parseString(value, options, function (err, result) {
 | 
			
		||||
                        if (err) { done(err); }
 | 
			
		||||
                        else {
 | 
			
		||||
                            RED.util.setMessageProperty(msg,node.property,result);
 | 
			
		||||
                            RED.util.setMessageProperty(msg,node.propertyOut,result);
 | 
			
		||||
                            send(msg);
 | 
			
		||||
                            done();
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,16 @@
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="yaml">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-property"><i class="fa fa-sign-in"></i> <span data-i18n="common.label.propertyIn"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-property" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
 | 
			
		||||
        <label for="node-input-propertyOut"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-propertyOut" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@@ -17,7 +21,10 @@
 | 
			
		||||
        defaults: {
 | 
			
		||||
            property: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true }),
 | 
			
		||||
                       label:RED._("node-red:common.label.property")},
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyIn")},
 | 
			
		||||
            propertyOut: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyOut")},
 | 
			
		||||
            name: {value:""}
 | 
			
		||||
        },
 | 
			
		||||
        inputs:1,
 | 
			
		||||
@@ -34,6 +41,10 @@
 | 
			
		||||
                $("#node-input-property").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-property").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            if (this.propertyOut === undefined) {
 | 
			
		||||
                $("#node-input-propertyOut").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-propertyOut").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,17 +2,19 @@
 | 
			
		||||
module.exports = function(RED) {
 | 
			
		||||
    "use strict";
 | 
			
		||||
    var yaml = require('js-yaml');
 | 
			
		||||
    const { getMessagePropertySafe } = require('../utils.js')(RED)
 | 
			
		||||
    function YAMLNode(n) {
 | 
			
		||||
        RED.nodes.createNode(this,n);
 | 
			
		||||
        this.property = n.property||"payload";
 | 
			
		||||
        this.propertyOut = n.propertyOut||this.property;
 | 
			
		||||
        var node = this;
 | 
			
		||||
        this.on("input", function(msg,send,done) {
 | 
			
		||||
            var value = RED.util.getMessageProperty(msg,node.property);
 | 
			
		||||
            var value = getMessagePropertySafe(msg,node.property);
 | 
			
		||||
            if (value !== undefined) {
 | 
			
		||||
                if (typeof value === "string") {
 | 
			
		||||
                    try {
 | 
			
		||||
                        value = yaml.load(value);
 | 
			
		||||
                        RED.util.setMessageProperty(msg,node.property,value);
 | 
			
		||||
                        RED.util.setMessageProperty(msg,node.propertyOut,value);
 | 
			
		||||
                        send(msg);
 | 
			
		||||
                        done();
 | 
			
		||||
                    }
 | 
			
		||||
@@ -22,7 +24,7 @@ module.exports = function(RED) {
 | 
			
		||||
                    if (!Buffer.isBuffer(value)) {
 | 
			
		||||
                        try {
 | 
			
		||||
                            value = yaml.dump(value);
 | 
			
		||||
                            RED.util.setMessageProperty(msg,node.property,value);
 | 
			
		||||
                            RED.util.setMessageProperty(msg,node.propertyOut,value);
 | 
			
		||||
                            send(msg);
 | 
			
		||||
                            done();
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="file">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row node-input-filename">
 | 
			
		||||
         <label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
 | 
			
		||||
         <input id="node-input-filename" type="text">
 | 
			
		||||
@@ -28,14 +32,14 @@
 | 
			
		||||
        <select type="text" id="node-input-encoding" style="width: 250px;">
 | 
			
		||||
        </select>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-tips"><span data-i18n="file.tip"></span></div>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<script type="text/html" data-template-name="file in">
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
         <label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
 | 
			
		||||
         <input id="node-input-filename" type="text">
 | 
			
		||||
@@ -61,8 +65,8 @@
 | 
			
		||||
        </select>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-name">
 | 
			
		||||
        <label for="node-input-propertyOut"><i class="fa fa-sign-out"></i> <span data-i18n="common.label.propertyOut"></span></label>
 | 
			
		||||
        <input type="text" id="node-input-propertyOut" style="width:70%;"/>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-tips"><span data-i18n="file.tip"></span></div>
 | 
			
		||||
</script>
 | 
			
		||||
@@ -299,6 +303,9 @@
 | 
			
		||||
            name: {value:""},
 | 
			
		||||
            filename: {value:"", validate: RED.validators.typedInput({ typeField: 'filenameType' }) },
 | 
			
		||||
            filenameType: {value:"str"},
 | 
			
		||||
            propertyOut: {value:"payload",required:true,
 | 
			
		||||
                       validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
 | 
			
		||||
                       label:RED._("node-red:common.label.propertyOut")},
 | 
			
		||||
            format: {value:"utf8"},
 | 
			
		||||
            chunk: {value:false},
 | 
			
		||||
            sendError: {value: false},
 | 
			
		||||
@@ -345,6 +352,10 @@
 | 
			
		||||
                types: [{label:RED._("node-red:file.label.path"), value:"str", icon:""}, "msg", "jsonata", "env"],
 | 
			
		||||
                typeField: $("#node-input-filenameType")
 | 
			
		||||
            });
 | 
			
		||||
            if (this.propertyOut === undefined) {
 | 
			
		||||
                $("#node-input-propertyOut").val("payload");
 | 
			
		||||
            }
 | 
			
		||||
            $("#node-input-propertyOut").typedInput({default:'msg',types:['msg']});
 | 
			
		||||
            if(typeof node.filenameType == 'undefined') {
 | 
			
		||||
                //existing node AND filenameType is not set - inplace (compatible) upgrade to new typedInput
 | 
			
		||||
                if(node.filename == "") { //was using empty value to denote msg.filename - set typedInput to match
 | 
			
		||||
 
 | 
			
		||||
@@ -286,6 +286,7 @@ module.exports = function(RED) {
 | 
			
		||||
        RED.nodes.createNode(this,n);
 | 
			
		||||
        this.filename = n.filename;
 | 
			
		||||
        this.filenameType = n.filenameType;
 | 
			
		||||
        this.propertyOut = n.propertyOut || "payload";
 | 
			
		||||
        this.format = n.format;
 | 
			
		||||
        this.chunk = false;
 | 
			
		||||
        this.encoding = n.encoding || "none";
 | 
			
		||||
@@ -370,7 +371,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                            m.topic = msg.topic;
 | 
			
		||||
                                            m.filename = msg.filename;
 | 
			
		||||
                                        }
 | 
			
		||||
                                        m.payload = bits[i];
 | 
			
		||||
                                        RED.util.setMessageProperty(m,node.propertyOut,bits[i]);
 | 
			
		||||
                                        m.parts= {index:count, ch:ch, type:type, id:msg._msgid}
 | 
			
		||||
                                        count += 1;
 | 
			
		||||
                                        nodeSend(m);
 | 
			
		||||
@@ -386,7 +387,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                        m.topic = msg.topic;
 | 
			
		||||
                                        m.filename = msg.filename;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    m.payload = chunk;
 | 
			
		||||
                                    RED.util.setMessageProperty(m,node.propertyOut,chunk);
 | 
			
		||||
                                    m.parts = {index:count, ch:ch, type:type, id:msg._msgid}
 | 
			
		||||
                                    count += 1;
 | 
			
		||||
                                    if (chunk.length < hwm) { // last chunk is smaller that high water mark = eof
 | 
			
		||||
@@ -405,7 +406,7 @@ module.exports = function(RED) {
 | 
			
		||||
                        node.error(err, msg);
 | 
			
		||||
                        if (node.sendError) {
 | 
			
		||||
                            var sendMessage = RED.util.cloneMessage(msg);
 | 
			
		||||
                            delete sendMessage.payload;
 | 
			
		||||
                            delete sendMessage[node.propertyOut];
 | 
			
		||||
                            sendMessage.error = err;
 | 
			
		||||
                            nodeSend(sendMessage);
 | 
			
		||||
                        }
 | 
			
		||||
@@ -414,9 +415,10 @@ module.exports = function(RED) {
 | 
			
		||||
                    .on('end', function() {
 | 
			
		||||
                        if (node.chunk === false) {
 | 
			
		||||
                            if (node.format === "utf8") {
 | 
			
		||||
                                msg.payload = decode(lines, node.encoding);
 | 
			
		||||
                                RED.util.setMessageProperty(msg,node.propertyOut,decode(lines, node.encoding));
 | 
			
		||||
                            } else {
 | 
			
		||||
                                RED.util.setMessageProperty(msg,node.propertyOut,lines);
 | 
			
		||||
                            }
 | 
			
		||||
                            else { msg.payload = lines; }
 | 
			
		||||
                            nodeSend(msg);
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (node.format === "lines") {
 | 
			
		||||
@@ -428,7 +430,7 @@ module.exports = function(RED) {
 | 
			
		||||
                                m.topic = msg.topic;
 | 
			
		||||
                                m.filename = msg.filename;
 | 
			
		||||
                            }
 | 
			
		||||
                            m.payload = spare;
 | 
			
		||||
                            RED.util.setMessageProperty(m,node.propertyOut,spare);
 | 
			
		||||
                            m.parts = {
 | 
			
		||||
                                index: count,
 | 
			
		||||
                                count: count + 1,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								packages/node_modules/@node-red/nodes/core/utils.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/node_modules/@node-red/nodes/core/utils.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
function utils(RED) {
 | 
			
		||||
    
 | 
			
		||||
    /** 
 | 
			
		||||
     * Returns the value of a property in a message object using a path. If not found, returns undefined.
 | 
			
		||||
     * @param {Object} msg - The message object.
 | 
			
		||||
     * @param {string} path - The path to the property.
 | 
			
		||||
     */
 | 
			
		||||
    function getMessagePropertySafe (msg, path) {
 | 
			
		||||
        try {
 | 
			
		||||
            return RED.util.getMessageProperty(msg, path)
 | 
			
		||||
        } catch (_e) {
 | 
			
		||||
            return undefined
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        getMessagePropertySafe
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = utils
 | 
			
		||||
@@ -7,6 +7,8 @@
 | 
			
		||||
            "username": "Username",
 | 
			
		||||
            "password": "Password",
 | 
			
		||||
            "property": "Property",
 | 
			
		||||
            "propertyIn": "Property In",
 | 
			
		||||
            "propertyOut": "Property Out",
 | 
			
		||||
            "selectNodes": "Select nodes...",
 | 
			
		||||
            "expand": "Expand"
 | 
			
		||||
        },
 | 
			
		||||
 
 | 
			
		||||
@@ -30,13 +30,19 @@ describe('range Node', function() {
 | 
			
		||||
        helper.stopServer(done);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should load some defaults', function(done) {
 | 
			
		||||
    it('should load with defaults', function(done) {
 | 
			
		||||
        var flow = [{"id":"rangeNode1","type":"range","name":"rangeNode"}];
 | 
			
		||||
        helper.load(rangeNode, flow, function() {
 | 
			
		||||
            var rangeNode1 = helper.getNode("rangeNode1");
 | 
			
		||||
            rangeNode1.should.have.property('name', 'rangeNode');
 | 
			
		||||
            rangeNode1.should.have.property('round', false);
 | 
			
		||||
            done();
 | 
			
		||||
            try {
 | 
			
		||||
                var rangeNode1 = helper.getNode("rangeNode1");
 | 
			
		||||
                rangeNode1.should.have.property('name', 'rangeNode');
 | 
			
		||||
                rangeNode1.should.have.property('round', false);
 | 
			
		||||
                rangeNode1.should.have.property('property', 'payload')
 | 
			
		||||
                rangeNode1.should.have.property('propertyOut', 'payload')
 | 
			
		||||
                done();
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                done(error);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -170,4 +176,23 @@ describe('range Node', function() {
 | 
			
		||||
            rangeNode1.receive({payload:"NOT A NUMBER"});
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('uses configured property to get input value and propertyOut to set output value', function (done) {
 | 
			
		||||
        var flow = [{ "id": "rangeNode1", "type": "range", "minin": 0, "maxin": 10, "minout": 0, "maxout": 100, "action": "scale", "round": true, "name": "rangeNode", "property": "payload.sub.prop", "propertyOut": "result", "wires": [["helperNode1"]] },
 | 
			
		||||
        { id: "helperNode1", type: "helper", wires: [] }]
 | 
			
		||||
        helper.load(rangeNode, flow, function () {
 | 
			
		||||
            var rangeNode1 = helper.getNode("rangeNode1")
 | 
			
		||||
            var helperNode1 = helper.getNode("helperNode1")
 | 
			
		||||
            helperNode1.on("input", function (msg) {
 | 
			
		||||
                try {
 | 
			
		||||
                    msg.should.have.property("result")
 | 
			
		||||
                    msg.result.should.equal(50)
 | 
			
		||||
                    done()
 | 
			
		||||
                } catch (err) {
 | 
			
		||||
                    done(err)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            rangeNode1.receive({ payload: { sub: { prop: 5 } } })
 | 
			
		||||
        });
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -60,6 +60,21 @@ describe('template node', function() {
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should load with defaults', function (done) {
 | 
			
		||||
        const flow = [{ id: "n1", type: "template", template: "payload={{payload}}" }]
 | 
			
		||||
        helper.load(templateNode, flow, function () {
 | 
			
		||||
            try {
 | 
			
		||||
                const n1 = helper.getNode("n1")
 | 
			
		||||
                n1.should.have.property('syntax', 'mustache')
 | 
			
		||||
                n1.should.have.property('field', 'payload') // `propertyOut` on this node is `field`
 | 
			
		||||
                n1.should.have.property('fieldType', 'msg')
 | 
			
		||||
                n1.should.have.property('outputFormat', 'str')
 | 
			
		||||
                done()
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                done(error)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('should modify payload using node-configured template', function(done) {
 | 
			
		||||
        var flow = [{id:"n1", type:"template", field:"payload", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",type:"helper"}];
 | 
			
		||||
 
 | 
			
		||||
@@ -518,6 +518,45 @@ describe('HTTP Request Node', function() {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('request', function() {
 | 
			
		||||
        it('should load with defaults', function(done) {
 | 
			
		||||
            const flow = [{id:"n1",type:"http request", name: "my http request",wires:[["n2"]]}]
 | 
			
		||||
            helper.load(httpRequestNode, flow, function() {
 | 
			
		||||
                try {
 | 
			
		||||
                    const n1 = helper.getNode("n1")
 | 
			
		||||
                    n1.should.have.property('name', 'my http request')
 | 
			
		||||
                    n1.should.not.have.property('method')
 | 
			
		||||
                    n1.should.have.property('property', 'payload')
 | 
			
		||||
                    n1.should.have.property('propertyOut', 'payload')
 | 
			
		||||
                    n1.should.have.property('ret', 'txt')
 | 
			
		||||
                    n1.should.have.property('reqTimeout', 120000)
 | 
			
		||||
                    n1.should.have.property('headers').and.be.an.Array().and.have.length(0)
 | 
			
		||||
                    n1.should.have.property('authType', 'basic')
 | 
			
		||||
                    done()
 | 
			
		||||
                } catch (error) {
 | 
			
		||||
                    done(error)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        it('should get using message properties specified for `property in` and `property out`', function (done) {
 | 
			
		||||
            const flow = [{ id: "n1", type: "http request", wires: [["n2"]], method: "GET", ret: "txt", property: 'body.data.in', propertyOut: 'result', url: getTestURL('/text') },
 | 
			
		||||
            { id: "n2", type: "helper" }]
 | 
			
		||||
            helper.load(httpRequestNode, flow, function () {
 | 
			
		||||
                const n1 = helper.getNode("n1")
 | 
			
		||||
                const n2 = helper.getNode("n2")
 | 
			
		||||
                n2.on("input", function (msg) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        msg.should.have.property('result', 'hello')
 | 
			
		||||
                        msg.should.have.property('statusCode', 200)
 | 
			
		||||
                        done()
 | 
			
		||||
                    } catch (err) {
 | 
			
		||||
                        done(err)
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
                n1.receive({ body: { data: { in: 'foo' } } })
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        it('should get plain text content', function(done) {
 | 
			
		||||
            var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/text')},
 | 
			
		||||
                {id:"n2", type:"helper"}];
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ const delayNode = require("nr-test-utils").require("@node-red/nodes/core/functio
 | 
			
		||||
const helper = require("node-red-node-test-helper");
 | 
			
		||||
// const { neq } = require("semver");
 | 
			
		||||
 | 
			
		||||
describe('CSV node (Legacy Mode)', function() {
 | 
			
		||||
describe.only('CSV node (Legacy Mode)', function() {
 | 
			
		||||
 | 
			
		||||
    before(function(done) {
 | 
			
		||||
        helper.startServer(done);
 | 
			
		||||
@@ -51,6 +51,8 @@ describe('CSV node (Legacy Mode)', function() {
 | 
			
		||||
                // n1.should.have.property('lineend', '\n');
 | 
			
		||||
                n1.should.have.property('multi', 'one');
 | 
			
		||||
                n1.should.have.property('hdrin', false);
 | 
			
		||||
                n1.should.have.property('property', 'payload');
 | 
			
		||||
                n1.should.have.property('propertyOut', 'payload');
 | 
			
		||||
                done();
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                done(error);
 | 
			
		||||
@@ -788,6 +790,26 @@ describe('CSV node (Legacy Mode)', function() {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it ('should use message properties specified for `property in` and `property out`', function(done) {
 | 
			
		||||
            const flow = [{ id: "n1", type: "csv", spec: "rfc", temp: "a,b,c,d", property: 'payload.sub.prop', propertyOut: 'result.sub_prop', wires: [["n2"]] },
 | 
			
		||||
            { id: "n2", type: "helper" }];
 | 
			
		||||
            helper.load(csvNode, flow, function () {
 | 
			
		||||
                const n1 = helper.getNode("n1");
 | 
			
		||||
                const n2 = helper.getNode("n2");
 | 
			
		||||
                n2.on("input", function (msg) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        msg.should.have.property('result').and.be.an.Object();
 | 
			
		||||
                        msg.result.should.have.property('sub_prop', { a: 1, b: 2, c: 3, d: 4 });
 | 
			
		||||
                        msg.should.have.property('columns', "a,b,c,d");
 | 
			
		||||
                        check_parts(msg, 0, 1);
 | 
			
		||||
                        done();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (e) { done(e); }
 | 
			
		||||
                });
 | 
			
		||||
                const testString = "1,2,3,4" + String.fromCharCode(10);
 | 
			
		||||
                n1.emit("input", { payload: { sub: { prop: testString } } });
 | 
			
		||||
            });
 | 
			
		||||
        })
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('json object to csv', function() {
 | 
			
		||||
@@ -1101,6 +1123,23 @@ describe('CSV node (Legacy Mode)', function() {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it ('should use message properties specified for `property in` and `property out`', function(done) {
 | 
			
		||||
            const flow = [{ id: "n1", type: "csv", spec: "rfc", temp: "a,b,c,d", ret: '\n', property: 'payload.sub.prop', propertyOut: 'result', wires: [["n2"]] }, // RFC-vs-Legacy difference - use line separator \n to satisfy original test
 | 
			
		||||
            { id: "n2", type: "helper" }];
 | 
			
		||||
            helper.load(csvNode, flow, function() {
 | 
			
		||||
                const n1 = helper.getNode("n1");
 | 
			
		||||
                const n2 = helper.getNode("n2");
 | 
			
		||||
                n2.on("input", function(msg) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        msg.should.have.property('result', '4,3,2,1\n');
 | 
			
		||||
                        done();
 | 
			
		||||
                    } catch(e) { done(e); }
 | 
			
		||||
                });
 | 
			
		||||
                const testJson = { d: 1, b: 3, c: 2, a: 4 };
 | 
			
		||||
                n1.emit("input", { payload: { sub: { prop: testJson } } });
 | 
			
		||||
            });
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should just pass through if no payload provided', function(done) {
 | 
			
		||||
@@ -1190,7 +1229,7 @@ describe('CSV node (Legacy Mode)', function() {
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
describe('CSV node (RFC Mode)', function () {
 | 
			
		||||
describe.only('CSV node (RFC Mode)', function () {
 | 
			
		||||
 | 
			
		||||
    before(function (done) {
 | 
			
		||||
        helper.startServer(done);
 | 
			
		||||
@@ -1219,6 +1258,8 @@ describe('CSV node (RFC Mode)', function () {
 | 
			
		||||
                n1.should.have.property('ret', '\r\n'); // RFC-Legacy difference
 | 
			
		||||
                n1.should.have.property('multi', 'one');
 | 
			
		||||
                n1.should.have.property('hdrin', false);
 | 
			
		||||
                n1.should.have.property('property', 'payload');
 | 
			
		||||
                n1.should.have.property('propertyOut', 'payload');
 | 
			
		||||
                done();
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                done(error);
 | 
			
		||||
@@ -1997,6 +2038,26 @@ describe('CSV node (RFC Mode)', function () {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it ('should use message properties specified for `property in` and `property out`', function(done) {
 | 
			
		||||
            const flow = [{ id: "n1", type: "csv", spec: "rfc", temp: "a,b,c,d", property: 'payload.sub.prop', propertyOut: 'result.sub_prop', wires: [["n2"]] },
 | 
			
		||||
            { id: "n2", type: "helper" }];
 | 
			
		||||
            helper.load(csvNode, flow, function () {
 | 
			
		||||
                const n1 = helper.getNode("n1");
 | 
			
		||||
                const n2 = helper.getNode("n2");
 | 
			
		||||
                n2.on("input", function (msg) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        msg.should.have.property('result').and.be.an.Object();
 | 
			
		||||
                        msg.result.should.have.property('sub_prop', { a: 1, b: 2, c: 3, d: 4 });
 | 
			
		||||
                        msg.should.have.property('columns', "a,b,c,d");
 | 
			
		||||
                        check_parts(msg, 0, 1);
 | 
			
		||||
                        done();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (e) { done(e); }
 | 
			
		||||
                });
 | 
			
		||||
                const testString = "1,2,3,4" + String.fromCharCode(10);
 | 
			
		||||
                n1.emit("input", { payload: { sub: { prop: testString } } });
 | 
			
		||||
            });
 | 
			
		||||
        })
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('json object to csv', function () {
 | 
			
		||||
@@ -2336,6 +2397,23 @@ describe('CSV node (RFC Mode)', function () {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it ('should use message properties specified for `property in` and `property out`', function(done) {
 | 
			
		||||
            const flow = [{ id: "n1", type: "csv", spec: "rfc", temp: "a,b,c,d", ret: '\n', property: 'payload.sub.prop', propertyOut: 'result', wires: [["n2"]] }, // RFC-vs-Legacy difference - use line separator \n to satisfy original test
 | 
			
		||||
            { id: "n2", type: "helper" }];
 | 
			
		||||
            helper.load(csvNode, flow, function() {
 | 
			
		||||
                const n1 = helper.getNode("n1");
 | 
			
		||||
                const n2 = helper.getNode("n2");
 | 
			
		||||
                n2.on("input", function(msg) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        msg.should.have.property('result', '4,3,2,1\n');
 | 
			
		||||
                        done();
 | 
			
		||||
                    } catch(e) { done(e); }
 | 
			
		||||
                });
 | 
			
		||||
                const testJson = { d: 1, b: 3, c: 2, a: 4 };
 | 
			
		||||
                n1.emit("input", { payload: { sub: { prop: testJson } } });
 | 
			
		||||
            });
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should just pass through if no payload provided', function (done) {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,25 @@ describe('JSON node', function() {
 | 
			
		||||
        helper.unload();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should be loaded with defaults', function(done) {
 | 
			
		||||
        const flow = [{id:"jn1",type:"json", name: 'json node',wires:[["jn2"]]}]
 | 
			
		||||
        helper.load(jsonNode, flow, function() {
 | 
			
		||||
            const n1 = helper.getNode("jn1")
 | 
			
		||||
            try {
 | 
			
		||||
                n1.should.have.property('name', 'json node')
 | 
			
		||||
                n1.should.have.property('property','payload')
 | 
			
		||||
                n1.should.have.property('propertyOut','payload')
 | 
			
		||||
                n1.should.have.property('schema', null)
 | 
			
		||||
                n1.should.have.property('compiledSchema', null)
 | 
			
		||||
                n1.should.have.property('action', '')
 | 
			
		||||
                n1.should.have.property('indent', 0)
 | 
			
		||||
                done();
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                done(error)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('should convert a valid json string to a javascript object', function(done) {
 | 
			
		||||
        var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
 | 
			
		||||
                    {id:"jn2", type:"helper"}];
 | 
			
		||||
@@ -587,4 +606,56 @@ describe('JSON node', function() {
 | 
			
		||||
            jn1.receive({payload:jsonObject, schema:schema});
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should convert a valid json string to a javascript object using message properties specified for `property in` and `property out`', function (done) {
 | 
			
		||||
        const flow = [{ id: "jn1", type: "json", property: "payload.sub.prop", propertyOut: "result", wires: [["jn2"]] },
 | 
			
		||||
        { id: "jn2", type: "helper" }]
 | 
			
		||||
        helper.load(jsonNode, flow, function () {
 | 
			
		||||
            const jn1 = helper.getNode("jn1")
 | 
			
		||||
            const jn2 = helper.getNode("jn2")
 | 
			
		||||
            jn2.on("input", function (msg) {
 | 
			
		||||
                msg.should.have.property('topic', 'bar')
 | 
			
		||||
                msg.should.have.property('result').and.be.an.Object()
 | 
			
		||||
                msg.result.should.have.property('employees')
 | 
			
		||||
                msg.result.employees[0].should.have.property('firstName', 'John')
 | 
			
		||||
                msg.result.employees[0].should.have.property('lastName', 'Smith')
 | 
			
		||||
                done()
 | 
			
		||||
            })
 | 
			
		||||
            const jsonString = ' {"employees":[{"firstName":"John", "lastName":"Smith"}]}\r\n '
 | 
			
		||||
            jn1.receive({ topic: "bar", payload: { sub: { prop: jsonString } } })
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('should convert a javascript object to a json string using message properties specified for `property in` and `property out`', function (done) {
 | 
			
		||||
        const flow = [{ id: "jn1", type: "json", property: "payload.sub.prop", propertyOut: "result", wires: [["jn2"]] },
 | 
			
		||||
        { id: "jn2", type: "helper" }]
 | 
			
		||||
        helper.load(jsonNode, flow, function () {
 | 
			
		||||
            const jn1 = helper.getNode("jn1")
 | 
			
		||||
            const jn2 = helper.getNode("jn2")
 | 
			
		||||
            jn2.on("input", function (msg) {
 | 
			
		||||
                msg.should.have.property('result').and.be.a.String()
 | 
			
		||||
                should.equal(msg.result, '{"employees":[{"firstName":"John","lastName":"Smith"}]}')
 | 
			
		||||
                done()
 | 
			
		||||
            })
 | 
			
		||||
            const obj = { employees: [{ firstName: "John", lastName: "Smith" }] }
 | 
			
		||||
            jn1.receive({ payload: { sub: { prop: obj } } })
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('should pass through if property specified for `property in` is missing', function (done) {
 | 
			
		||||
        const flow = [{ id: "jn1", type: "json", property: "payload.sub.prop", propertyOut: "result", wires: [["jn2"]] },
 | 
			
		||||
        { id: "jn2", type: "helper" }]
 | 
			
		||||
        helper.load(jsonNode, flow, function () {
 | 
			
		||||
            const jn1 = helper.getNode("jn1")
 | 
			
		||||
            const jn2 = helper.getNode("jn2")
 | 
			
		||||
            const obj = { employees: [{ firstName: "John", lastName: "Smith" }] }
 | 
			
		||||
            jn2.on("input", function (msg) {
 | 
			
		||||
                msg.should.not.have.property('result') // never set
 | 
			
		||||
                msg.should.have.propertyByPath('payload', 'sub', 'propBAD').and.be.an.Object() // unchanged
 | 
			
		||||
                msg.payload.sub.propBAD.should.deepEqual(obj)
 | 
			
		||||
                done()
 | 
			
		||||
            })
 | 
			
		||||
            jn1.receive({ payload: { sub: { propBAD: obj } } })
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -32,12 +32,18 @@ describe('XML node', function() {
 | 
			
		||||
        helper.unload();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should be loaded', function(done) {
 | 
			
		||||
    it('should load with defaults', function(done) {
 | 
			
		||||
        var flow = [{id:"xmlNode1", type:"xml", name: "xmlNode" }];
 | 
			
		||||
        helper.load(xmlNode, flow, function() {
 | 
			
		||||
            var xmlNode1 = helper.getNode("xmlNode1");
 | 
			
		||||
            xmlNode1.should.have.property('name', 'xmlNode');
 | 
			
		||||
            done();
 | 
			
		||||
            try {
 | 
			
		||||
                var xmlNode1 = helper.getNode("xmlNode1");
 | 
			
		||||
                xmlNode1.should.have.property('name', 'xmlNode');
 | 
			
		||||
                xmlNode1.should.have.property('property', 'payload')
 | 
			
		||||
                xmlNode1.should.have.property('propertyOut', 'payload')
 | 
			
		||||
                done();
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                done(error);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -195,4 +201,41 @@ describe('XML node', function() {
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should convert a valid xml string to a javascript object using message properties specified for `property in` and `property out`', function(done) {
 | 
			
		||||
        const flow = [{ id: "n1", type: "xml", property: "payload.sub.prop", propertyOut: 'result', wires: [["n2"]], func: "return msg;" },
 | 
			
		||||
        { id: "n2", type: "helper" }]
 | 
			
		||||
        helper.load(xmlNode, flow, function () {
 | 
			
		||||
            const n1 = helper.getNode("n1")
 | 
			
		||||
            const n2 = helper.getNode("n2")
 | 
			
		||||
            n2.on("input", function (msg) {
 | 
			
		||||
                msg.should.have.property('topic', 'bar')
 | 
			
		||||
                msg.should.have.property('result').and.be.an.Object()
 | 
			
		||||
                msg.result.should.have.property('employees')
 | 
			
		||||
                msg.result.employees.should.have.property('firstName')
 | 
			
		||||
                should.equal(msg.result.employees.firstName[0], 'John')
 | 
			
		||||
                msg.result.employees.should.have.property('lastName')
 | 
			
		||||
                should.equal(msg.result.employees.lastName[0], 'Smith')
 | 
			
		||||
                done()
 | 
			
		||||
            })
 | 
			
		||||
            const string = '  <employees><firstName>John</firstName><lastName>Smith</lastName></employees>\r\n  '
 | 
			
		||||
            n1.receive({ topic: "bar", payload: { sub: { prop: string } } })
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('should convert a javascript object to an xml string using message properties specified for `property in` and `property out`', function (done) {
 | 
			
		||||
        const flow = [{ id: "n1", type: "xml", property: "payload.sub.prop", propertyOut: 'result', wires: [["n2"]], func: "return msg" },
 | 
			
		||||
        { id: "n2", type: "helper" }]
 | 
			
		||||
        helper.load(xmlNode, flow, function () {
 | 
			
		||||
            const n1 = helper.getNode("n1")
 | 
			
		||||
            const n2 = helper.getNode("n2")
 | 
			
		||||
            n2.on("input", function (msg) {
 | 
			
		||||
                msg.should.have.property('topic', 'bar')
 | 
			
		||||
                const index = msg.result.indexOf('<employees><firstName>John</firstName><lastName>Smith</lastName></employees>')
 | 
			
		||||
                index.should.be.above(-1)
 | 
			
		||||
                done()
 | 
			
		||||
            })
 | 
			
		||||
            const obj = { "employees": { "firstName": ["John"], "lastName": ["Smith"] } }
 | 
			
		||||
            n1.receive({ topic: "bar", payload: { sub: { prop: obj } } })
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -32,12 +32,18 @@ describe('YAML node', function() {
 | 
			
		||||
        helper.unload();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should be loaded', function(done) {
 | 
			
		||||
    it('should load with defaults', function(done) {
 | 
			
		||||
        var flow = [{id:"yamlNode1", type:"yaml", name: "yamlNode" }];
 | 
			
		||||
        helper.load(yamlNode, flow, function() {
 | 
			
		||||
            var yamlNode1 = helper.getNode("yamlNode1");
 | 
			
		||||
            yamlNode1.should.have.property('name', 'yamlNode');
 | 
			
		||||
            done();
 | 
			
		||||
            try {
 | 
			
		||||
                var yamlNode1 = helper.getNode("yamlNode1");
 | 
			
		||||
                yamlNode1.should.have.property('name', 'yamlNode');
 | 
			
		||||
                yamlNode1.should.have.property('property', 'payload')
 | 
			
		||||
                yamlNode1.should.have.property('propertyOut', 'payload')
 | 
			
		||||
                done();
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                done(error);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -192,4 +198,36 @@ describe('YAML node', function() {
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should convert a valid yaml string to a javascript object using message properties specified for `property in` and `property out`', function (done) {
 | 
			
		||||
        const flow = [{ id: "yn1", type: "yaml", property: "payload.sub.prop", propertyOut: "result", wires: [["yn2"]], func: "return msg;" },
 | 
			
		||||
        { id: "yn2", type: "helper" }]
 | 
			
		||||
        helper.load(yamlNode, flow, function () {
 | 
			
		||||
            const yn1 = helper.getNode("yn1")
 | 
			
		||||
            const yn2 = helper.getNode("yn2")
 | 
			
		||||
            yn2.on("input", function (msg) {
 | 
			
		||||
                msg.should.have.property('topic', 'bar')
 | 
			
		||||
                msg.result.should.have.property('employees')
 | 
			
		||||
                msg.result.employees[0].should.have.property('firstName', 'John')
 | 
			
		||||
                msg.result.employees[0].should.have.property('lastName', 'Smith')
 | 
			
		||||
                done()
 | 
			
		||||
            })
 | 
			
		||||
            const yamlString = "employees:\n  - firstName: John\n    lastName: Smith\n"
 | 
			
		||||
            yn1.receive({ topic: "bar", payload: { sub: { prop: yamlString } } })
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('should convert a javascript object to a yaml string using message properties specified for `property in` and `property out`', function (done) {
 | 
			
		||||
        const flow = [{ id: "yn1", type: "yaml", property: "payload.sub.prop", propertyOut: "result", wires: [["yn2"]], func: "return msg;" },
 | 
			
		||||
        { id: "yn2", type: "helper" }]
 | 
			
		||||
        helper.load(yamlNode, flow, function () {
 | 
			
		||||
            const yn1 = helper.getNode("yn1")
 | 
			
		||||
            const yn2 = helper.getNode("yn2")
 | 
			
		||||
            yn2.on("input", function (msg) {
 | 
			
		||||
                should.equal(msg.result, "employees:\n  - firstName: John\n    lastName: Smith\n")
 | 
			
		||||
                done()
 | 
			
		||||
            })
 | 
			
		||||
            const obj = { employees: [{ firstName: "John", lastName: "Smith" }] }
 | 
			
		||||
            yn1.receive({ payload: { sub: { prop: obj } } })
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ describe('file Nodes', function() {
 | 
			
		||||
 | 
			
		||||
        var relativePathToFile = "50-file-test-file.txt";
 | 
			
		||||
        var resourcesDir = path.join(__dirname,"..","..","..","resources");
 | 
			
		||||
        resourcesDir = resourcesDir.replace(/\\/g, '/'); // Windows
 | 
			
		||||
        var fileToTest = path.join(resourcesDir,relativePathToFile);
 | 
			
		||||
        var wait = 250;
 | 
			
		||||
 | 
			
		||||
@@ -240,7 +241,7 @@ describe('file Nodes', function() {
 | 
			
		||||
                                f.should.equal("Line1\nLine2\nLine3\nLine4");
 | 
			
		||||
                            }
 | 
			
		||||
                            else {
 | 
			
		||||
                                f.should.have.length(23);
 | 
			
		||||
                                f.should.have.length(26);
 | 
			
		||||
                                f.should.equal("Line1\r\nLine2\r\nLine3\r\nLine4");
 | 
			
		||||
                            }
 | 
			
		||||
                            done();
 | 
			
		||||
@@ -1220,6 +1221,7 @@ describe('file Nodes', function() {
 | 
			
		||||
 | 
			
		||||
        var relativePathToFile = "50-file-test-file.txt";
 | 
			
		||||
        var resourcesDir = path.join(__dirname,"..","..","..","resources");
 | 
			
		||||
        resourcesDir = resourcesDir.replace(/\\/g, '/'); // Windows
 | 
			
		||||
        var fileToTest = path.join(resourcesDir,relativePathToFile);
 | 
			
		||||
        var fileToTest2 = "\t"+path.join(resourcesDir,relativePathToFile)+"\r\n";
 | 
			
		||||
        var wait = 150;
 | 
			
		||||
@@ -1237,11 +1239,12 @@ describe('file Nodes', function() {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should be loaded', function(done) {
 | 
			
		||||
        it('should load with defaults', function(done) {
 | 
			
		||||
            var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest, "format":"utf8"}];
 | 
			
		||||
            helper.load(fileNode, flow, function() {
 | 
			
		||||
                var n1 = helper.getNode("fileInNode1");
 | 
			
		||||
                n1.should.have.property('name', 'fileInNode');
 | 
			
		||||
                n1.should.have.property('propertyOut', 'payload')
 | 
			
		||||
                done();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
@@ -1528,6 +1531,23 @@ describe('file Nodes', function() {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should read in a file and output to the message property specified in `propertyOut`', function (done) {
 | 
			
		||||
            const flow = [{ id: "fileInNode1", type: "file in", name: "fileInNode", "filename": fileToTest, "format": "", propertyOut: "file-data", wires: [["n2"]] },
 | 
			
		||||
            { id: "n2", type: "helper" }]
 | 
			
		||||
            helper.load(fileNode, flow, function () {
 | 
			
		||||
                const n1 = helper.getNode("fileInNode1")
 | 
			
		||||
                const n2 = helper.getNode("n2")
 | 
			
		||||
                n2.on("input", function (msg) {
 | 
			
		||||
                    msg.should.have.property('file-data')
 | 
			
		||||
                    Buffer.isBuffer(msg['file-data']).should.be.true()
 | 
			
		||||
                    msg['file-data'].should.have.length(40)
 | 
			
		||||
                    msg['file-data'].toString().should.equal('File message line 1\nFile message line 2\n')
 | 
			
		||||
                    done()
 | 
			
		||||
                })
 | 
			
		||||
                n1.receive({ payload: "" })
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        describe('encodings', function() {
 | 
			
		||||
 | 
			
		||||
            function checkReadWithEncoding(enc, data, done) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user