Compare commits

..

4 Commits

Author SHA1 Message Date
Nick O'Leary
1a3cc06935 Use rfdc module for cloning when we know its pure JSON 2024-05-03 16:45:50 +01:00
Nick O'Leary
a712a9363b Merge pull request #4674 from kazuhitoyokoi/dev-addjpn
Add Japanese translations for 4.0.0-beta.2
2024-05-03 16:18:50 +01:00
Kazuhito Yokoi
437c28e2b8 Fix typos in welcome tour for 4.0.0-beta.2 2024-04-28 21:27:25 +09:00
Kazuhito Yokoi
c05d18ada1 Add Japanese translations for 4.0.0-beta.2 2024-04-28 21:22:15 +09:00
36 changed files with 217 additions and 667 deletions

View File

@@ -73,6 +73,7 @@
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.2",
"rfdc": "^1.3.1",
"semver": "7.5.4",
"tar": "6.2.1",
"tough-cookie": "4.1.3",

View File

@@ -658,6 +658,9 @@
"body": "<p>Removing '__module__'</p><p>Removing the node will uninstall it from Node-RED. The node may continue to use resources until Node-RED is restarted.</p>",
"title": "Remove nodes"
},
"removePlugin": {
"body": "<p>Removed plugin __module__. Please reload the editor to clear left-overs.</p>"
},
"update": {
"body": "<p>Updating '__module__'</p><p>Updating the node will require a restart of Node-RED to complete the update. This must be done manually.</p>",
"title": "Update nodes"
@@ -669,7 +672,8 @@
"review": "Open node information",
"install": "Install",
"remove": "Remove",
"update": "Update"
"update": "Update",
"understood": "Understood"
}
}
}

View File

@@ -614,6 +614,8 @@
},
"nodeCount": "__label__ 個のノード",
"nodeCount_plural": "__label__ 個のノード",
"pluginCount": "__count__ 個のプラグイン",
"pluginCount_plural": "__count__ 個のプラグイン",
"moduleCount": "__count__ 個のモジュール",
"moduleCount_plural": "__count__ 個のモジュール",
"inuse": "使用中",
@@ -641,6 +643,7 @@
"errors": {
"catalogLoadFailed": "<p>ノードのカタログの読み込みに失敗しました。</p><p>詳細はブラウザのコンソールを確認してください。</p>",
"installFailed": "<p>追加処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
"installTimeout": "<p>バックグラウンドでインストールが継続されます。</p><p>完了した時にノードが表示されます。詳細はログを確認してください。</p>",
"removeFailed": "<p>削除処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
"updateFailed": "<p>更新処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
"enableFailed": "<p>有効化処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
@@ -655,6 +658,9 @@
"body": "<p>__module__ を削除します。</p><p>Node-REDからードを削除します。ードはNode-REDが再起動されるまで、リソースを使い続ける可能性があります。</p>",
"title": "ノードを削除"
},
"removePlugin": {
"body": "<p>プラグイン __module__ を削除しました。ブラウザを再読み込みして残った表示を消してください。</p>"
},
"update": {
"body": "<p>__module__ を更新します。</p><p>更新を完了するには手動でNode-REDを再起動する必要があります。</p>",
"title": "ノードの更新"
@@ -666,7 +672,8 @@
"review": "ノードの情報を参照",
"install": "追加",
"remove": "削除",
"update": "更新"
"update": "更新",
"understood": "了解"
}
}
}

View File

@@ -1346,13 +1346,13 @@ RED.palette.editor = (function() {
});
if (!found_onremove) {
let removeNotify = RED.notify("Removed plugin " + entry.name + ". Please reload the editor to clear left-overs.",{
let removeNotify = RED.notify(RED._("palette.editor.confirm.removePlugin.body",{module:entry.name}),{
modal: true,
fixed: true,
type: 'warning',
buttons: [
{
text: "Understood",
text: RED._("palette.editor.confirm.button.understood"),
class:"primary",
click: function(e) {
removeNotify.close();

View File

@@ -16,7 +16,8 @@ export default {
},
{
title: {
"en-US": "Multiplayer Mode"
"en-US": "Multiplayer Mode",
"ja": "複数ユーザ同時利用モード"
},
image: 'images/nr4-multiplayer.png',
description: {
@@ -24,46 +25,58 @@ export default {
to work with when you have multiple people editing flows at the same time.</p>
<p>When this feature is enabled, you will now see who else has the editor open and some
basic information on where they are in the editor.</p>
<p>Check the release post for details on how to enable this feature in your settings file.</p>`
<p>Check the release post for details on how to enable this feature in your settings file.</p>`,
"ja": `<p>本リリースには、複数ユーザが同時にフローを編集する時に、Node-REDをより使いやすくするのための最初の微修正が入っています。</p>
<p>本機能を有効にすると、誰がエディタを開いているか、その人がエディタ上のどこにいるかの基本的な情報が表示されます。</p>
<p>設定ファイルで本機能を有効化する方法の詳細は、リリースの投稿を確認してください。</p>`
}
},
{
title: {
"en-US": "Better Configuration Node UX"
"en-US": "Better Configuration Node UX",
"ja": "設定ードのUXが向上"
},
image: 'images/nr4-config-select.png',
description: {
"en-US": `<p>The Configuration node selection UI has had a small update to have a dedicated 'add' button
next to the select box.</p>
<p>It's a small change, but should make it easier to work with your config nodes.</p>`
<p>It's a small change, but should make it easier to work with your config nodes.</p>`,
"ja": `<p>設定ードを選択するUIが修正され、選択ボックスの隣に専用の「追加」ボタンが追加されました。</p>
<p>微修正ですが設定ノードの操作が容易になります。</p>`
}
},
{
title: {
"en-US": "Remembering palette state"
"en-US": "Remembering palette state",
"ja": "パレットの状態を維持"
},
description: {
"en-US": `<p>The palette now remembers what categories you have hidden between reloads - as well as any
filter you have applied.</p>`
filter you have applied.</p>`,
"ja": `<p>パレット上で非表示にしたカテゴリや適用したフィルタが、リロードしても記憶されるようになりました。</p>`
}
},
{
title: {
"en-US": "Plugins shown in the Palette Manager"
"en-US": "Plugins shown in the Palette Manager",
"ja": "パレット管理にプラグインを表示"
},
image: 'images/nr4-plugins.png',
description: {
"en-US": `<p>The palette manager now shows any plugin modules you have installed, such as
<code>node-red-debugger</code>. Previously they would only be shown if they plugin include
nodes for the palette.</p>`
<code>node-red-debugger</code>. Previously they would only be shown if the plugins include
nodes for the palette.</p>`,
"ja": `<p>パレットの管理に <code>node-red-debugger</code> の様なインストールしたプラグインが表示されます。以前はプラグインにパレット向けのノードが含まれている時のみ表示されていました。</p>`
}
},
{
title: {
"en-US": "That's if for Beta 2!"
"en-US": "That's it for Beta 2!",
"ja": "ベータ2については以上です!"
},
description: {
"en-US": `<p>Keep clicking through to see what was added in Beta 1</p>`
"en-US": `<p>Keep clicking through to see what was added in Beta 1</p>`,
"ja": `<p>クリックを続けてベータ1で追加された内容を確認してください。</p>`
}
},
{

View File

@@ -1,11 +1,7 @@
<script type="text/html" data-template-name="range">
<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>
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
<input type="text" id="node-input-property" style="width:calc(70% - 1px)"/>
</div>
<div class="form-row">
@@ -35,8 +31,8 @@
</div>
<br/>
<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%;"/>
<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-tips" id="node-tip"><span data-i18n="range.tip"></span></div>
</script>
@@ -61,13 +57,9 @@
action: {value:"scale"},
round: {value:false},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.propertyIn"),
label:RED._("node-red:common.label.property"),
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,
@@ -85,10 +77,6 @@
$("#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>

View File

@@ -16,7 +16,6 @@
module.exports = function(RED) {
"use strict";
const { getMessagePropertySafe } = require('../utils.js')(RED)
function RangeNode(n) {
RED.nodes.createNode(this, n);
this.action = n.action;
@@ -26,11 +25,10 @@ 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 = getMessagePropertySafe(msg, node.property);
var value = RED.util.getMessageProperty(msg,node.property);
if (value !== undefined) {
var n = Number(value);
if (!isNaN(n)) {
@@ -48,7 +46,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.propertyOut,value);
RED.util.setMessageProperty(msg,node.property,value);
send(msg);
}
else { node.log(RED._("range.errors.notnumber")+": "+value); }

View File

@@ -4,6 +4,11 @@
<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">
@@ -36,18 +41,14 @@
</select>
</div>
<div class="form-row">
<label for="node-input-output"><i class="fa fa-sign-out"></i> <span data-i18n="template.label.output"></span></label>
<label for="node-input-output"><i class="fa fa-long-arrow-right"></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">

View File

@@ -15,16 +15,6 @@
-->
<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%;">
@@ -108,7 +98,7 @@
<div class="form-row">
<label for="node-input-ret"><i class="fa fa-sign-out"></i> <span data-i18n="httpin.label.return"></span></label>
<label for="node-input-ret"><i class="fa fa-arrow-left"></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>
@@ -117,10 +107,7 @@
</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>
@@ -128,7 +115,10 @@
<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">
@@ -245,13 +235,7 @@
insecureHTTPParser: {value: false},
authType: {value: ""},
senderr: {value: false},
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")}
headers: { value: [] }
},
credentials: {
user: {type:"text"},
@@ -442,15 +426,6 @@
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')) {

View File

@@ -29,7 +29,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
@@ -68,8 +68,6 @@ 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";
@@ -433,14 +431,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 value !== "undefined") {
if (opts.headers['content-type'] == 'multipart/form-data' && typeof value === "object") {
if (method !== 'GET' && method !== 'HEAD' && typeof msg.payload !== "undefined") {
if (opts.headers['content-type'] == 'multipart/form-data' && typeof msg.payload === "object") {
let formData = new FormData();
for (var opt in value) {
if (value.hasOwnProperty(opt)) {
var val = value[opt];
for (var opt in msg.payload) {
if (msg.payload.hasOwnProperty(opt)) {
var val = msg.payload[opt];
if (val !== undefined && val !== null) {
if (typeof val === 'string' || Buffer.isBuffer(val)) {
formData.append(opt, val);
@@ -457,15 +455,15 @@ in your Node-RED user directory (${RED.settings.userDir}).
delete opts.headers['content-type'];
opts.body = formData;
} else {
if (typeof value === "string" || Buffer.isBuffer(value)) {
payload = value;
} else if (typeof value == "number") {
payload = value + "";
if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
payload = msg.payload;
} else if (typeof msg.payload == "number") {
payload = msg.payload+"";
} else {
if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') {
payload = querystring.stringify(value);
payload = querystring.stringify(msg.payload);
} else {
payload = JSON.stringify(value);
payload = JSON.stringify(msg.payload);
if (opts.headers['content-type'] == null) {
opts.headers[ctSet] = "application/json";
}
@@ -483,13 +481,13 @@ in your Node-RED user directory (${RED.settings.userDir}).
}
if (method == 'GET' && typeof value !== "undefined" && paytoqs) {
if (typeof value === "object") {
if (method == 'GET' && typeof msg.payload !== "undefined" && paytoqs) {
if (typeof msg.payload === "object") {
try {
if (url.indexOf("?") !== -1) {
url += (url.endsWith("?")?"":"&") + querystring.stringify(value);
url += (url.endsWith("?")?"":"&") + querystring.stringify(msg.payload);
} else {
url += "?" + querystring.stringify(value);
url += "?" + querystring.stringify(msg.payload);
}
} catch(err) {
@@ -503,14 +501,14 @@ in your Node-RED user directory (${RED.settings.userDir}).
nodeDone();
return;
}
} else if ( method == "GET" && typeof value !== "undefined" && paytobody) {
} else if ( method == "GET" && typeof msg.payload !== "undefined" && paytobody) {
opts.allowGetBody = true;
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;
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;
}
}
@@ -599,7 +597,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
msg.statusCode = res.statusCode;
msg.headers = res.headers;
msg.responseUrl = res.url;
let result = res.body;
msg.payload = res.body;
msg.redirectList = redirectList;
msg.retry = 0;
@@ -624,15 +622,14 @@ in your Node-RED user directory (${RED.settings.userDir}).
// Convert the payload to the required return type
if (node.ret !== "bin") {
result = result.toString('utf8'); // txt
msg.payload = msg.payload.toString('utf8'); // txt
if (node.ret === "obj") {
if (msg.statusCode == 204){result= "{}"};
try { result = JSON.parse(result); } // obj
if (msg.statusCode == 204){msg.payload= "{}"};
try { msg.payload = JSON.parse(msg.payload); } // obj
catch(e) { node.warn(RED._("httpin.errors.json-error")); }
}
}
RED.util.setMessageProperty(msg, node.propertyOut, result)
node.status({});
nodeSend(msg);
nodeDone();
@@ -650,7 +647,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
node.error(err,msg);
node.status({fill:"red", shape:"ring", text:err.code});
}
RED.util.setMessageProperty(msg, node.propertyOut, err.toString() + " : " + url)
msg.payload = err.toString() + " : " + url;
msg.statusCode = err.code || (err.response?err.response.statusCode:undefined);
if (node.metric() && timingLog) {
emitTimingMetricLog(err.timings, msg);

View File

@@ -1,13 +1,5 @@
<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">
@@ -40,8 +32,8 @@
</div>
</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%;"/>
<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>
<hr align="middle"/>
<div class="form-row">
@@ -110,13 +102,7 @@
skip: {value:"0"},
strings: {value:true},
include_empty_strings: {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")}
include_null_values: {value:""}
},
inputs:1,
outputs:1,
@@ -128,15 +114,6 @@
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); }

View File

@@ -15,11 +15,9 @@
**/
module.exports = function(RED) {
"use strict";
const csv = require('./lib/csv')
const { getMessagePropertySafe } = require('../utils.js')(RED)
"use strict";
function CSVNode(n) {
RED.nodes.createNode(this,n)
const node = this
@@ -28,9 +26,6 @@ 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");
@@ -71,44 +66,43 @@ module.exports = function(RED) {
if (msg.hasOwnProperty("reset")) {
node.hdrSent = false;
}
let inputData = getMessagePropertySafe(msg, node.property)
if (typeof inputData !== "undefined") {
if (typeof inputData == "object") { // convert object to CSV string
if (msg.hasOwnProperty("payload")) {
if (typeof msg.payload == "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(inputData)) { inputData = [ inputData ]; }
if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
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(inputData[0]);
template = Object.keys(msg.payload[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 < 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;
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;
}
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(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("\n") !== -1) { // add quotes if any "\n"
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;
}
}
ou.push(inputData[s].join(node.sep));
ou.push(msg.payload[s].join(node.sep));
}
else {
if ((template.length === 1) && (template[0] === '') && (msg.hasOwnProperty("columns"))) {
@@ -121,16 +115,16 @@ module.exports = function(RED) {
tmpwarn = false;
}
const row = [];
for (var p in inputData[0]) {
for (var p in msg.payload[0]) {
/* istanbul ignore else */
if (inputData[s].hasOwnProperty(p)) {
if (msg.payload[s].hasOwnProperty(p)) {
/* istanbul ignore else */
if (typeof inputData[s][p] !== "object") {
if (typeof msg.payload[s][p] !== "object") {
// Fix to honour include null values flag
//if (typeof inputData[s][p] !== "object" || (node.include_null_values === true && inputData[s][p] === null)) {
//if (typeof msg.payload[s][p] !== "object" || (node.include_null_values === true && msg.payload[s][p] === null)) {
var q = "";
if (inputData[s][p] !== undefined) {
q += inputData[s][p];
if (msg.payload[s][p] !== undefined) {
q += msg.payload[s][p];
}
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
q = q.replace(/"/g, '""');
@@ -155,7 +149,7 @@ module.exports = function(RED) {
var tt = template[t];
if (template[t].indexOf('"') >=0 ) { tt = "'"+tt+"'"; }
else { tt = '"'+tt+'"'; }
var p = RED.util.getMessageProperty(inputData[s] || {}, tt);
var p = RED.util.getMessageProperty(msg,'payload["'+s+'"]['+tt+']');
/* istanbul ignore else */
if (p === undefined) { p = ""; }
// fix to honour include null values flag
@@ -176,17 +170,16 @@ module.exports = function(RED) {
}
}
// join lines, don't forget to add the last new line
inputData = ou.join(node.ret) + node.ret;
RED.util.setMessageProperty(msg, node.propertyOut, inputData)
msg.payload = ou.join(node.ret) + node.ret;
msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
if (inputData !== '') {
if (msg.payload !== '') {
send(msg);
}
done();
}
catch(e) { done(e); }
}
else if (typeof inputData == "string") { // convert CSV string to object
else if (typeof msg.payload == "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
@@ -195,7 +188,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 = inputData;
var line = msg.payload;
var linecount = 0;
var tmp = "";
var has_parts = msg.hasOwnProperty("parts");
@@ -289,13 +282,13 @@ module.exports = function(RED) {
}
if (node.multi !== "one") {
RED.util.setMessageProperty(msg, node.propertyOut, a);
msg.payload = a;
if (has_parts && nocr <= 1) {
if (JSON.stringify(o) !== "{}") {
node.store.push(o);
}
if (msg.parts.index + 1 === msg.parts.count) {
RED.util.setMessageProperty(msg, node.propertyOut, node.store);
msg.payload = node.store;
msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
delete msg.parts;
send(msg);
@@ -312,7 +305,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(',');
RED.util.setMessageProperty(newMessage, node.propertyOut, a[i])
newMessage.payload = a[i];
if (!has_parts) {
newMessage.parts = {
id: msg._msgid,
@@ -418,8 +411,8 @@ module.exports = function(RED) {
if (msg.hasOwnProperty("reset")) {
node.hdrSent = false
}
let inputData = getMessagePropertySafe(msg, node.property)
if (typeof inputData !== "undefined") {
if (msg.hasOwnProperty("payload")) {
let inputData = msg.payload
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?
@@ -524,10 +517,9 @@ module.exports = function(RED) {
}
// join lines, don't forget to add the last new line
const result = stringBuilder.join(node.ret) + node.ret
RED.util.setMessageProperty(msg, node.propertyOut, result)
msg.payload = stringBuilder.join(node.ret) + node.ret
msg.columns = templateArrayToColumnString(template)
if (result !== '') { send(msg) }
if (msg.payload !== '') { send(msg) }
done()
}
catch (e) {
@@ -622,7 +614,7 @@ module.exports = function(RED) {
node.store.push(...data)
}
if (msg.parts.index + 1 === msg.parts.count) {
RED.util.setMessageProperty(msg, node.propertyOut, node.store)
msg.payload = node.store
msg.columns = csvParseResult.header
// msg._mode = 'RFC4180 mode'
delete msg.parts
@@ -633,7 +625,7 @@ module.exports = function(RED) {
else {
msg.columns = csvParseResult.header
// msg._mode = 'RFC4180 mode'
RED.util.setMessageProperty(msg, node.propertyOut, data)
msg.payload = data
send(msg); // finally send the array
}
}
@@ -642,7 +634,7 @@ module.exports = function(RED) {
for (let row = 0; row < len; row++) {
const newMessage = RED.util.cloneMessage(msg)
newMessage.columns = csvParseResult.header
RED.util.setMessageProperty(newMessage, node.propertyOut, data[row])
newMessage.payload = data[row]
if (!has_parts) {
newMessage.parts = {
id: msg._msgid,

View File

@@ -1,13 +1,5 @@
<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">
@@ -17,8 +9,12 @@
</select>
</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%;"/>
<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">
</div>
<hr align="middle"/>
<div class="form-row node-json-to-json-options">
@@ -37,10 +33,7 @@
name: {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")},
label:RED._("node-red:json.label.property")},
action: {value:""},
pretty: {value:false}
},
@@ -57,11 +50,7 @@
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();

View File

@@ -19,14 +19,12 @@ 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;
@@ -49,7 +47,7 @@ module.exports = function(RED) {
}
validate = true;
}
var value = getMessagePropertySafe(msg,node.property);
var value = RED.util.getMessageProperty(msg,node.property);
if (value !== undefined) {
if (typeof value === "string" || Buffer.isBuffer(value)) {
// if (Buffer.isBuffer(value) && node.action !== "obj") {
@@ -58,7 +56,7 @@ module.exports = function(RED) {
// else
if (node.action === "" || node.action === "obj") {
try {
RED.util.setMessageProperty(msg,node.propertyOut,JSON.parse(value));
RED.util.setMessageProperty(msg,node.property,JSON.parse(value));
if (validate) {
if (this.compiledSchema(msg[node.property])) {
delete msg.schema;
@@ -97,7 +95,7 @@ module.exports = function(RED) {
try {
if (validate) {
if (this.compiledSchema(value)) {
RED.util.setMessageProperty(msg,node.propertyOut,JSON.stringify(value,null,node.indent));
RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
delete msg.schema;
send(msg);
done();
@@ -106,7 +104,7 @@ module.exports = function(RED) {
done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
}
} else {
RED.util.setMessageProperty(msg,node.propertyOut,JSON.stringify(value,null,node.indent));
RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
send(msg);
done();
}

View File

@@ -1,16 +1,12 @@
<script type="text/html" data-template-name="xml">
<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>
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
<input type="text" id="node-input-property" style="width:70%;"/>
</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%;"/>
<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>
<hr align="middle"/>
<div class="form-row">
@@ -31,11 +27,7 @@
defaults: {
name: {value:""},
property: {value:"payload",required:true,
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"),
label:RED._("node-red:common.label.property"),
validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true })},
attr: {value:""},
chr: {value:""}
@@ -53,11 +45,7 @@
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>

View File

@@ -3,17 +3,15 @@ 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 = getMessagePropertySafe(msg,node.property);
var value = RED.util.getMessageProperty(msg,node.property);
if (value !== undefined) {
var options;
if (typeof value === "object") {
@@ -22,7 +20,7 @@ module.exports = function(RED) {
options.async = false;
var builder = new xml2js.Builder(options);
value = builder.buildObject(value, options);
RED.util.setMessageProperty(msg,node.propertyOut,value);
RED.util.setMessageProperty(msg,node.property,value);
send(msg);
done();
}
@@ -35,7 +33,7 @@ module.exports = function(RED) {
parseString(value, options, function (err, result) {
if (err) { done(err); }
else {
RED.util.setMessageProperty(msg,node.propertyOut,result);
RED.util.setMessageProperty(msg,node.property,result);
send(msg);
done();
}

View File

@@ -1,16 +1,12 @@
<script type="text/html" data-template-name="yaml">
<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>
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="common.label.property"></span></label>
<input type="text" id="node-input-property" style="width:70%;"/>
</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%;"/>
<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>
@@ -21,10 +17,7 @@
defaults: {
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")},
label:RED._("node-red:common.label.property")},
name: {value:""}
},
inputs:1,
@@ -41,10 +34,6 @@
$("#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>

View File

@@ -2,19 +2,17 @@
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 = getMessagePropertySafe(msg,node.property);
var value = RED.util.getMessageProperty(msg,node.property);
if (value !== undefined) {
if (typeof value === "string") {
try {
value = yaml.load(value);
RED.util.setMessageProperty(msg,node.propertyOut,value);
RED.util.setMessageProperty(msg,node.property,value);
send(msg);
done();
}
@@ -24,7 +22,7 @@ module.exports = function(RED) {
if (!Buffer.isBuffer(value)) {
try {
value = yaml.dump(value);
RED.util.setMessageProperty(msg,node.propertyOut,value);
RED.util.setMessageProperty(msg,node.property,value);
send(msg);
done();
}

View File

@@ -1,9 +1,5 @@
<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">
@@ -32,14 +28,14 @@
<select type="text" id="node-input-encoding" style="width: 250px;">
</select>
</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-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-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
<input id="node-input-filename" type="text">
@@ -65,8 +61,8 @@
</select>
</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%;"/>
<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>
@@ -303,9 +299,6 @@
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},
@@ -352,10 +345,6 @@
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

View File

@@ -286,7 +286,6 @@ 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";
@@ -371,7 +370,7 @@ module.exports = function(RED) {
m.topic = msg.topic;
m.filename = msg.filename;
}
RED.util.setMessageProperty(m,node.propertyOut,bits[i]);
m.payload = bits[i];
m.parts= {index:count, ch:ch, type:type, id:msg._msgid}
count += 1;
nodeSend(m);
@@ -387,7 +386,7 @@ module.exports = function(RED) {
m.topic = msg.topic;
m.filename = msg.filename;
}
RED.util.setMessageProperty(m,node.propertyOut,chunk);
m.payload = 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
@@ -406,7 +405,7 @@ module.exports = function(RED) {
node.error(err, msg);
if (node.sendError) {
var sendMessage = RED.util.cloneMessage(msg);
delete sendMessage[node.propertyOut];
delete sendMessage.payload;
sendMessage.error = err;
nodeSend(sendMessage);
}
@@ -415,10 +414,9 @@ module.exports = function(RED) {
.on('end', function() {
if (node.chunk === false) {
if (node.format === "utf8") {
RED.util.setMessageProperty(msg,node.propertyOut,decode(lines, node.encoding));
} else {
RED.util.setMessageProperty(msg,node.propertyOut,lines);
msg.payload = decode(lines, node.encoding);
}
else { msg.payload = lines; }
nodeSend(msg);
}
else if (node.format === "lines") {
@@ -430,7 +428,7 @@ module.exports = function(RED) {
m.topic = msg.topic;
m.filename = msg.filename;
}
RED.util.setMessageProperty(m,node.propertyOut,spare);
m.payload = spare;
m.parts = {
index: count,
count: count + 1,

View File

@@ -1,21 +0,0 @@
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

View File

@@ -7,8 +7,6 @@
"username": "Username",
"password": "Password",
"property": "Property",
"propertyIn": "Property In",
"propertyOut": "Property Out",
"selectNodes": "Select nodes...",
"expand": "Expand"
},

View File

@@ -15,6 +15,7 @@
**/
const clone = require("clone");
const jsonClone = require("rfdc")();
const Flow = require('./Flow').Flow;
const context = require('../nodes/context');
const util = require("util");
@@ -108,7 +109,7 @@ class Subflow extends Flow {
}
}
subflowInternalFlowConfig.subflows = clone(subflowDef.subflows || {});
subflowInternalFlowConfig.subflows = jsonClone(subflowDef.subflows || {});
remapSubflowNodes(subflowInternalFlowConfig.configs,node_map);
remapSubflowNodes(subflowInternalFlowConfig.nodes,node_map);
@@ -220,7 +221,7 @@ class Subflow extends Flow {
}
if (this.subflowDef.in) {
subflowInstanceConfig.wires = this.subflowDef.in.map(function(n) { return n.wires.map(function(w) { return self.node_map[w.id].id;})})
subflowInstanceConfig._originalWires = clone(subflowInstanceConfig.wires);
subflowInstanceConfig._originalWires = jsonClone(subflowInstanceConfig.wires);
}
this.node = new Node(subflowInstanceConfig);
@@ -244,14 +245,14 @@ class Subflow extends Flow {
if (self.subflowDef.out) {
var node,wires,i,j;
// Restore the original wiring to the internal nodes
subflowInstanceConfig.wires = clone(subflowInstanceConfig._originalWires);
subflowInstanceConfig.wires = jsonClone(subflowInstanceConfig._originalWires);
for (i=0;i<self.subflowDef.out.length;i++) {
wires = self.subflowDef.out[i].wires;
for (j=0;j<wires.length;j++) {
if (wires[j].id != self.subflowDef.id) {
node = self.node_map[wires[j].id];
if (node && node._originalWires) {
node.wires = clone(node._originalWires);
node.wires = jsonClone(node._originalWires);
}
}
}
@@ -300,7 +301,7 @@ class Subflow extends Flow {
var node = self.node_map[wires[j].id];
if (node) {
if (!node._originalWires) {
node._originalWires = clone(node.wires);
node._originalWires = jsonClone(node.wires);
}
node.wires[wires[j].port] = (node.wires[wires[j].port]||[]).concat(this.subflowInstance.wires[i]);
} else {
@@ -323,7 +324,7 @@ class Subflow extends Flow {
var node = self.node_map[wires[j].id];
if (node) {
if (!node._originalWires) {
node._originalWires = clone(node.wires);
node._originalWires = jsonClone(node.wires);
}
node.wires[wires[j].port] = (node.wires[wires[j].port]||[]);
node.wires[wires[j].port].push(subflowStatusId);
@@ -463,7 +464,7 @@ class Subflow extends Flow {
* @return {[type]} [description]
*/
function createNodeInSubflow(subflowInstanceId, def) {
let node = clone(def);
let node = jsonClone(def);
let nid = `${subflowInstanceId}-${node.id}` //redUtil.generateId();
// console.log("Create Node In subflow",node._alias, "--->",nid, "(",node.type,")")
// node_map[node.id] = node;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
**/
var clone = require("clone");
const jsonClone = require("rfdc")();
var Flow = require('./Flow');
@@ -140,16 +140,16 @@ function setFlows(_config,_credentials,type,muteLog,forceStart,user) {
if (type === "load") {
isLoad = true;
configSavePromise = loadFlows().then(function(_config) {
config = clone(_config.flows);
newFlowConfig = flowUtil.parseConfig(clone(config));
config = jsonClone(_config.flows);
newFlowConfig = flowUtil.parseConfig(jsonClone(config));
type = "full";
return _config.rev;
});
} else {
// Clone the provided config so it can be manipulated
config = clone(_config);
config = jsonClone(_config);
// Parse the configuration
newFlowConfig = flowUtil.parseConfig(clone(config));
newFlowConfig = flowUtil.parseConfig(jsonClone(config));
// Generate a diff to identify what has changed
diff = flowUtil.diffConfigs(activeFlowConfig,newFlowConfig);
@@ -609,7 +609,7 @@ async function addFlow(flow, user) {
nodes.push(node);
}
}
var newConfig = clone(activeConfig.flows);
var newConfig = jsonClone(activeConfig.flows);
newConfig = newConfig.concat(nodes);
return setFlows(newConfig, null, 'flows', true, null, user).then(function() {
@@ -650,7 +650,7 @@ function getFlow(id) {
var nodeIds = Object.keys(flow.nodes);
if (nodeIds.length > 0) {
result.nodes = nodeIds.map(function(nodeId) {
var node = clone(flow.nodes[nodeId]);
var node = jsonClone(flow.nodes[nodeId]);
if (node.type === 'link out') {
delete node.wires;
}
@@ -662,7 +662,7 @@ function getFlow(id) {
if (flow.configs) {
var configIds = Object.keys(flow.configs);
result.configs = configIds.map(function(configId) {
const node = clone(flow.configs[configId]);
const node = jsonClone(flow.configs[configId]);
delete node.credentials;
return node
@@ -674,17 +674,17 @@ function getFlow(id) {
if (flow.subflows) {
var subflowIds = Object.keys(flow.subflows);
result.subflows = subflowIds.map(function(subflowId) {
var subflow = clone(flow.subflows[subflowId]);
var subflow = jsonClone(flow.subflows[subflowId]);
var nodeIds = Object.keys(subflow.nodes);
subflow.nodes = nodeIds.map(function(id) {
const node = clone(subflow.nodes[id])
const node = jsonClone(subflow.nodes[id])
delete node.credentials
return node
});
if (subflow.configs) {
var configIds = Object.keys(subflow.configs);
subflow.configs = configIds.map(function(id) {
const node = clone(subflow.configs[id])
const node = jsonClone(subflow.configs[id])
delete node.credentials
return node
})
@@ -709,7 +709,7 @@ async function updateFlow(id,newFlow, user) {
}
label = activeFlowConfig.flows[id].label;
}
var newConfig = clone(activeConfig.flows);
var newConfig = jsonClone(activeConfig.flows);
var nodes;
if (id === 'global') {
@@ -779,7 +779,7 @@ async function removeFlow(id, user) {
throw e;
}
var newConfig = clone(activeConfig.flows);
var newConfig = jsonClone(activeConfig.flows);
newConfig = newConfig.filter(function(node) {
return node.z !== id && node.id !== id;
});

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
const clone = require("clone");
const jsonClone = require("rfdc")();
const redUtil = require("@node-red/util").util;
const Log = require("@node-red/util").log;
const typeRegistry = require("@node-red/registry");
@@ -175,7 +175,7 @@ async function createNode(flow,config) {
try {
var nodeTypeConstructor = typeRegistry.get(type);
if (typeof nodeTypeConstructor === "function") {
var conf = clone(config);
var conf = jsonClone(config);
delete conf.credentials;
try {
Object.defineProperty(conf,'_module', {value: typeRegistry.getNodeInfo(type), enumerable: false, writable: true })
@@ -202,8 +202,8 @@ async function createNode(flow,config) {
var subflowInstanceConfig = subflowConfig.subflows[nodeTypeConstructor.subflow.id];
delete subflowConfig.subflows[nodeTypeConstructor.subflow.id];
subflowInstanceConfig.subflows = subflowConfig.subflows;
var instanceConfig = clone(config);
instanceConfig.env = clone(nodeTypeConstructor.subflow.env);
var instanceConfig = jsonClone(config);
instanceConfig.env = jsonClone(nodeTypeConstructor.subflow.env);
instanceConfig.env = nodeTypeConstructor.subflow.env.map(nodeProp => {
var nodePropType;
@@ -256,7 +256,7 @@ function parseConfig(config) {
flow.missingTypes = [];
config.forEach(function (n) {
flow.allNodes[n.id] = clone(n);
flow.allNodes[n.id] = jsonClone(n);
if (n.type === 'tab') {
flow.flows[n.id] = n;
flow.flows[n.id].subflows = {};

View File

@@ -14,9 +14,8 @@
* limitations under the License.
**/
var path = require("path");
var fs = require("fs");
var clone = require("clone");
const jsonClone = require("rfdc")();
var util = require("util");
var registry = require("@node-red/registry");
@@ -98,7 +97,7 @@ function createNode(node,def) {
}
var creds = credentials.get(id);
if (creds) {
creds = clone(creds);
creds = jsonClone(creds);
//console.log("Attaching credentials to ",node.id);
// allow $(foo) syntax to substitute env variables for credentials also...
for (var p in creds) {

View File

@@ -25,6 +25,7 @@
"removing-modules": "設定からモジュールを削除します",
"added-types": "追加したノード:",
"removed-types": "削除したノード:",
"removed-plugins": "削除したプラグイン:",
"install": {
"invalid": "不正なモジュール名",
"installing": "モジュール __name__, バージョン: __version__ をインストールします",

View File

@@ -22,6 +22,7 @@
"clone": "2.1.2",
"express": "4.19.2",
"fs-extra": "11.1.1",
"json-stringify-safe": "5.0.1"
"json-stringify-safe": "5.0.1",
"rfdc": "^1.3.1"
}
}

View File

@@ -30,19 +30,13 @@ describe('range Node', function() {
helper.stopServer(done);
});
it('should load with defaults', function(done) {
it('should load some defaults', function(done) {
var flow = [{"id":"rangeNode1","type":"range","name":"rangeNode"}];
helper.load(rangeNode, flow, function() {
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);
}
var rangeNode1 = helper.getNode("rangeNode1");
rangeNode1.should.have.property('name', 'rangeNode');
rangeNode1.should.have.property('round', false);
done();
});
});
@@ -176,23 +170,4 @@ 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 } } })
});
})
});

View File

@@ -60,21 +60,6 @@ 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"}];

View File

@@ -515,45 +515,6 @@ 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"}];

View File

@@ -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.only('CSV node (Legacy Mode)', function() {
describe('CSV node (Legacy Mode)', function() {
before(function(done) {
helper.startServer(done);
@@ -51,8 +51,6 @@ describe.only('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);
@@ -790,26 +788,6 @@ describe.only('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() {
@@ -1123,23 +1101,6 @@ describe.only('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) {
@@ -1229,7 +1190,7 @@ describe.only('CSV node (Legacy Mode)', function() {
});
});
describe.only('CSV node (RFC Mode)', function () {
describe('CSV node (RFC Mode)', function () {
before(function (done) {
helper.startServer(done);
@@ -1258,8 +1219,6 @@ describe.only('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);
@@ -2038,26 +1997,6 @@ describe.only('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 () {
@@ -2397,23 +2336,6 @@ describe.only('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) {

View File

@@ -32,25 +32,6 @@ 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"}];
@@ -606,56 +587,4 @@ 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 } } })
})
})
});

View File

@@ -32,18 +32,12 @@ describe('XML node', function() {
helper.unload();
});
it('should load with defaults', function(done) {
it('should be loaded', function(done) {
var flow = [{id:"xmlNode1", type:"xml", name: "xmlNode" }];
helper.load(xmlNode, flow, function() {
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);
}
var xmlNode1 = helper.getNode("xmlNode1");
xmlNode1.should.have.property('name', 'xmlNode');
done();
});
});
@@ -201,41 +195,4 @@ 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 } } })
})
})
});

View File

@@ -32,18 +32,12 @@ describe('YAML node', function() {
helper.unload();
});
it('should load with defaults', function(done) {
it('should be loaded', function(done) {
var flow = [{id:"yamlNode1", type:"yaml", name: "yamlNode" }];
helper.load(yamlNode, flow, function() {
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);
}
var yamlNode1 = helper.getNode("yamlNode1");
yamlNode1.should.have.property('name', 'yamlNode');
done();
});
});
@@ -198,36 +192,4 @@ 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 } } })
})
})
});

View File

@@ -43,7 +43,6 @@ 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;
@@ -241,7 +240,7 @@ describe('file Nodes', function() {
f.should.equal("Line1\nLine2\nLine3\nLine4");
}
else {
f.should.have.length(26);
f.should.have.length(23);
f.should.equal("Line1\r\nLine2\r\nLine3\r\nLine4");
}
done();
@@ -1221,7 +1220,6 @@ 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;
@@ -1239,12 +1237,11 @@ describe('file Nodes', function() {
});
});
it('should load with defaults', function(done) {
it('should be loaded', 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();
});
});
@@ -1531,23 +1528,6 @@ 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) {