mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge branch 'master' into http-request-form-array
This commit is contained in:
commit
4c1d7ad2d2
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@ -5,6 +5,9 @@ on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
name: 'Update node-red-docker image'
|
||||
|
6
.github/workflows/tests.yml
vendored
6
.github/workflows/tests.yml
vendored
@ -6,8 +6,14 @@ on:
|
||||
pull_request:
|
||||
branches: [ master, dev ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
checks: write # for coverallsapp/github-action to create new checks
|
||||
contents: read # for actions/checkout to fetch code
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
|
0
packages/node_modules/@node-red/editor-client/locales/de/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/de/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/de/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/de/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/de/jsonata.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/de/jsonata.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/en-US/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/en-US/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ko/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ko/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ko/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ko/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ko/jsonata.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ko/jsonata.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ru/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ru/editor.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ru/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ru/infotips.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ru/jsonata.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/locales/ru/jsonata.json
vendored
Executable file → Normal file
@ -1965,7 +1965,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const keepNodesCurrentZ = reimport && n.z && RED.workspaces.contains(n.z)
|
||||
const keepNodesCurrentZ = reimport && n.z && (RED.workspaces.contains(n.z) || RED.nodes.subflow(n.z))
|
||||
if (!keepNodesCurrentZ && n.z && !workspace_map[n.z] && !subflow_map[n.z]) {
|
||||
n.z = activeWorkspace;
|
||||
}
|
||||
@ -2067,7 +2067,7 @@ RED.nodes = (function() {
|
||||
node.id = getID();
|
||||
} else {
|
||||
node.id = n.id;
|
||||
const keepNodesCurrentZ = reimport && node.z && RED.workspaces.contains(node.z)
|
||||
const keepNodesCurrentZ = reimport && node.z && (RED.workspaces.contains(node.z) || RED.nodes.subflow(node.z))
|
||||
if (!keepNodesCurrentZ && (node.z == null || (!workspace_map[node.z] && !subflow_map[node.z]))) {
|
||||
if (createMissingWorkspace) {
|
||||
if (missingWorkspace === null) {
|
||||
@ -2740,6 +2740,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
const nodeGroupMap = {}
|
||||
var replaceNodeIds = Object.keys(replaceNodes);
|
||||
if (replaceNodeIds.length > 0) {
|
||||
var reimportList = [];
|
||||
@ -2750,6 +2751,12 @@ RED.nodes = (function() {
|
||||
} else {
|
||||
allNodes.removeNode(n);
|
||||
}
|
||||
if (n.g) {
|
||||
// reimporting a node *without* including its group object
|
||||
// will cause the g property to be cleared. Cache it
|
||||
// here so we can restore it
|
||||
nodeGroupMap[n.id] = n.g
|
||||
}
|
||||
reimportList.push(convertNode(n));
|
||||
RED.events.emit('nodes:remove',n);
|
||||
});
|
||||
@ -2771,6 +2778,18 @@ RED.nodes = (function() {
|
||||
var newNodeMap = {};
|
||||
result.nodes.forEach(function(n) {
|
||||
newNodeMap[n.id] = n;
|
||||
if (nodeGroupMap[n.id]) {
|
||||
// This node is in a group - need to substitute the
|
||||
// node reference inside the group
|
||||
n.g = nodeGroupMap[n.id]
|
||||
const group = RED.nodes.group(n.g)
|
||||
if (group) {
|
||||
var index = group.nodes.findIndex(gn => gn.id === n.id)
|
||||
if (index > -1) {
|
||||
group.nodes[index] = n
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
RED.nodes.eachLink(function(l) {
|
||||
if (newNodeMap.hasOwnProperty(l.source.id)) {
|
||||
|
@ -146,7 +146,7 @@
|
||||
{ value: "reset", source: ["delay","trigger","join","rbe"] },
|
||||
{ value: "responseCookies", source: ["http request"] },
|
||||
{ value: "responseTopic", source: ["mqtt"] },
|
||||
{ value: "responseURL", source: ["http request"] },
|
||||
{ value: "responseUrl", source: ["http request"] },
|
||||
{ value: "restartTimeout", source: ["join"] },
|
||||
{ value: "retain", source: ["mqtt"] },
|
||||
{ value: "schema", source: ["json"] },
|
||||
|
@ -238,6 +238,7 @@ RED.editor = (function() {
|
||||
var valid = validateNodeProperty(node, defaults, property,value);
|
||||
if (((typeof valid) === "string") || !valid) {
|
||||
input.addClass("input-error");
|
||||
input.next(".red-ui-typedInput-container").addClass("input-error");
|
||||
if ((typeof valid) === "string") {
|
||||
var tooltip = input.data("tooltip");
|
||||
if (tooltip) {
|
||||
@ -250,6 +251,7 @@ RED.editor = (function() {
|
||||
}
|
||||
} else {
|
||||
input.removeClass("input-error");
|
||||
input.next(".red-ui-typedInput-container").removeClass("input-error");
|
||||
var tooltip = input.data("tooltip");
|
||||
if (tooltip) {
|
||||
input.data("tooltip", null);
|
||||
|
0
packages/node_modules/@node-red/editor-client/src/js/ui/library.js
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/src/js/ui/library.js
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/src/js/ui/palette.js
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/src/js/ui/palette.js
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js
vendored
Executable file → Normal file
3
packages/node_modules/@node-red/editor-client/src/js/ui/view.js
vendored
Executable file → Normal file
3
packages/node_modules/@node-red/editor-client/src/js/ui/view.js
vendored
Executable file → Normal file
@ -3369,6 +3369,9 @@ RED.view = (function() {
|
||||
}
|
||||
if (dblClickPrimed && mousedown_node == d && clickElapsed > 0 && clickElapsed < dblClickInterval) {
|
||||
mouse_mode = RED.state.DEFAULT;
|
||||
// Avoid dbl click causing text selection.
|
||||
d3.event.preventDefault()
|
||||
document.getSelection().removeAllRanges()
|
||||
if (d.type != "subflow") {
|
||||
if (/^subflow:/.test(d.type) && (d3.event.ctrlKey || d3.event.metaKey)) {
|
||||
RED.workspaces.show(d.type.substring(8));
|
||||
|
@ -4,7 +4,7 @@
|
||||
<label style="width: auto" for="node-input-scope" data-i18n="catch.label.source"></label>
|
||||
<select id="node-input-scope-select">
|
||||
<option value="all" data-i18n="catch.scope.all"></option>
|
||||
<option value="target" data-i18n="catch.scope.selected"></options>
|
||||
<option value="target" data-i18n="catch.scope.selected"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-input-uncaught-row">
|
||||
|
@ -451,11 +451,13 @@
|
||||
tabs.activateTab("func-tab-body");
|
||||
|
||||
$( "#node-input-outputs" ).spinner({
|
||||
min:0,
|
||||
min: 0,
|
||||
max: 500,
|
||||
change: function(event, ui) {
|
||||
var value = this.value;
|
||||
if (!value.match(/^\d+$/)) { value = 1; }
|
||||
else if (value < this.min) { value = this.min; }
|
||||
var value = parseInt(this.value);
|
||||
value = isNaN(value) ? 1 : value;
|
||||
value = Math.max(value, parseInt($(this).attr("aria-valuemin")));
|
||||
value = Math.min(value, parseInt($(this).attr("aria-valuemax")));
|
||||
if (value !== this.value) { $(this).spinner("value", value); }
|
||||
}
|
||||
});
|
||||
|
@ -318,7 +318,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
var r = node.rules[currentRule];
|
||||
if (r.t === "move") {
|
||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) {
|
||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1) && (r.p !== r.to)) {
|
||||
applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => {
|
||||
applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => {
|
||||
completeApplyingRules(msg,currentRule,done);
|
||||
|
@ -21,6 +21,7 @@
|
||||
<option value="javascript">JavaScript</option>
|
||||
<option value="css">CSS</option>
|
||||
<option value="markdown">Markdown</option>
|
||||
<option value="php">PHP</option>
|
||||
<option value="python">Python</option>
|
||||
<option value="sql">SQL</option>
|
||||
<option value="yaml">YAML</option>
|
||||
|
@ -421,7 +421,11 @@
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
|
||||
var typedInputNoneOpt = { value: 'none', label: '', hasValue: false };
|
||||
var typedInputNoneOpt = {
|
||||
value: 'none',
|
||||
label: RED._("node-red:mqtt.label.none"),
|
||||
hasValue: false
|
||||
};
|
||||
var makeTypedInputOpt = function(value){
|
||||
return {
|
||||
value: value,
|
||||
@ -436,7 +440,11 @@
|
||||
makeTypedInputOpt("text/csv"),
|
||||
makeTypedInputOpt("text/html"),
|
||||
makeTypedInputOpt("text/plain"),
|
||||
{value:"other", label:""}
|
||||
{
|
||||
value: "other",
|
||||
label: RED._("node-red:mqtt.label.other"),
|
||||
icon: "red/images/typedInput/az.svg"
|
||||
}
|
||||
];
|
||||
|
||||
function getDefaultContentType(value) {
|
||||
@ -499,17 +507,17 @@
|
||||
cleansession: {value: true},
|
||||
birthTopic: {value:"", validate:validateMQTTPublishTopic},
|
||||
birthQos: {value:"0"},
|
||||
birthRetain: {value:false},
|
||||
birthRetain: {value:"false"},
|
||||
birthPayload: {value:""},
|
||||
birthMsg: { value: {}},
|
||||
closeTopic: {value:"", validate:validateMQTTPublishTopic},
|
||||
closeQos: {value:"0"},
|
||||
closeRetain: {value:false},
|
||||
closeRetain: {value:"false"},
|
||||
closePayload: {value:""},
|
||||
closeMsg: { value: {}},
|
||||
willTopic: {value:"", validate:validateMQTTPublishTopic},
|
||||
willQos: {value:"0"},
|
||||
willRetain: {value:false},
|
||||
willRetain: {value:"false"},
|
||||
willPayload: {value:""},
|
||||
willMsg: { value: {}},
|
||||
userProps: { value: ""},
|
||||
|
@ -366,6 +366,16 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateStatus(node, allNodes) {
|
||||
let setStatus = setStatusDisconnected
|
||||
if(node.connecting) {
|
||||
setStatus = setStatusConnecting
|
||||
} else if(node.connected) {
|
||||
setStatus = setStatusConnected
|
||||
}
|
||||
setStatus(node, allNodes)
|
||||
}
|
||||
|
||||
function setStatusDisconnected(node, allNodes) {
|
||||
if(allNodes) {
|
||||
for (var id in node.users) {
|
||||
@ -459,7 +469,6 @@ module.exports = function(RED) {
|
||||
if(!opts || typeof opts !== "object") {
|
||||
return; //nothing to change, simply return
|
||||
}
|
||||
const originalBrokerURL = node.brokerurl;
|
||||
|
||||
//apply property changes (only if the property exists in the opts object)
|
||||
setIfHasProperty(opts, node, "url", init);
|
||||
@ -468,7 +477,6 @@ module.exports = function(RED) {
|
||||
setIfHasProperty(opts, node, "clientid", init);
|
||||
setIfHasProperty(opts, node, "autoConnect", init);
|
||||
setIfHasProperty(opts, node, "usetls", init);
|
||||
setIfHasProperty(opts, node, "usews", init);
|
||||
setIfHasProperty(opts, node, "verifyservercert", init);
|
||||
setIfHasProperty(opts, node, "compatmode", init);
|
||||
setIfHasProperty(opts, node, "protocolVersion", init);
|
||||
@ -571,9 +579,6 @@ module.exports = function(RED) {
|
||||
if (typeof node.usetls === 'undefined') {
|
||||
node.usetls = false;
|
||||
}
|
||||
if (typeof node.usews === 'undefined') {
|
||||
node.usews = false;
|
||||
}
|
||||
if (typeof node.verifyservercert === 'undefined') {
|
||||
node.verifyservercert = false;
|
||||
}
|
||||
@ -702,13 +707,17 @@ module.exports = function(RED) {
|
||||
if (Object.keys(node.users).length === 1) {
|
||||
if(node.autoConnect) {
|
||||
node.connect();
|
||||
//update nodes status
|
||||
setTimeout(function() {
|
||||
updateStatus(node, true)
|
||||
}, 1)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
node.deregister = function(mqttNode,done) {
|
||||
node.deregister = function(mqttNode, done, autoDisconnect) {
|
||||
delete node.users[mqttNode.id];
|
||||
if (!node.closing && node.connected && Object.keys(node.users).length === 0) {
|
||||
if (autoDisconnect && !node.closing && node.connected && Object.keys(node.users).length === 0) {
|
||||
node.disconnect();
|
||||
}
|
||||
done();
|
||||
@ -1000,7 +1009,7 @@ module.exports = function(RED) {
|
||||
node.client.publish(msg.topic, msg.payload, options, function (err) {
|
||||
if (done) {
|
||||
done(err)
|
||||
} else {
|
||||
} else if(err) {
|
||||
node.error(err, msg)
|
||||
}
|
||||
})
|
||||
@ -1225,7 +1234,7 @@ module.exports = function(RED) {
|
||||
} else {
|
||||
node.brokerConn.unsubscribe(node.topic,node.id, removed);
|
||||
}
|
||||
node.brokerConn.deregister(node, done);
|
||||
node.brokerConn.deregister(node, done, removed);
|
||||
node.brokerConn = null;
|
||||
} else {
|
||||
done();
|
||||
@ -1288,9 +1297,9 @@ module.exports = function(RED) {
|
||||
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
||||
}
|
||||
node.brokerConn.register(node);
|
||||
node.on('close', function(done) {
|
||||
node.on('close', function(removed, done) {
|
||||
if (node.brokerConn) {
|
||||
node.brokerConn.deregister(node,done);
|
||||
node.brokerConn.deregister(node, done, removed)
|
||||
node.brokerConn = null;
|
||||
} else {
|
||||
done();
|
||||
|
@ -46,7 +46,7 @@ module.exports = function(RED) {
|
||||
isText = true;
|
||||
} else if (parsedType.type !== "application") {
|
||||
isText = false;
|
||||
} else if ((parsedType.subtype !== "octet-stream")
|
||||
} else if ((parsedType.subtype !== "octet-stream")
|
||||
&& (parsedType.subtype !== "cbor")
|
||||
&& (parsedType.subtype !== "x-protobuf")) {
|
||||
checkUTF = true;
|
||||
@ -200,6 +200,15 @@ module.exports = function(RED) {
|
||||
this.callback = function(req,res) {
|
||||
var msgid = RED.util.generateId();
|
||||
res._msgid = msgid;
|
||||
// Since Node 15, req.headers are lazily computed and the property
|
||||
// marked as non-enumerable.
|
||||
// That means it doesn't show up in the Debug sidebar.
|
||||
// This redefines the property causing it to be evaluated *and*
|
||||
// marked as enumerable again.
|
||||
Object.defineProperty(req, 'headers', {
|
||||
value: req.headers,
|
||||
enumerable: true
|
||||
})
|
||||
if (node.method.match(/^(post|delete|put|options|patch)$/)) {
|
||||
node.send({_msgid:msgid,req:req,res:createResponseWrapper(node,res),payload:req.body});
|
||||
} else if (node.method == "get") {
|
||||
|
@ -110,7 +110,12 @@ module.exports = function(RED) {
|
||||
if (msg.payload[s].hasOwnProperty(p)) {
|
||||
/* istanbul ignore else */
|
||||
if (typeof msg.payload[s][p] !== "object") {
|
||||
var q = "" + msg.payload[s][p];
|
||||
// Fix to honour include null values flag
|
||||
//if (typeof msg.payload[s][p] !== "object" || (node.include_null_values === true && msg.payload[s][p] === null)) {
|
||||
var q = "";
|
||||
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, '""');
|
||||
ou += node.quo + q + node.quo + node.sep;
|
||||
@ -130,9 +135,15 @@ module.exports = function(RED) {
|
||||
ou += node.sep;
|
||||
}
|
||||
else {
|
||||
var p = RED.util.ensureString(RED.util.getMessageProperty(msg,"payload["+s+"]['"+template[t]+"']"));
|
||||
var tt = template[t];
|
||||
if (template[t].indexOf('"') >=0 ) { tt = "'"+tt+"'"; }
|
||||
else { tt = '"'+tt+'"'; }
|
||||
var p = RED.util.getMessageProperty(msg,'payload["'+s+'"]['+tt+']');
|
||||
/* istanbul ignore else */
|
||||
if (p === "undefined") { p = ""; }
|
||||
if (p === undefined) { p = ""; }
|
||||
// fix to honour include null values flag
|
||||
//if (p === null && node.include_null_values !== true) { p = "";}
|
||||
p = RED.util.ensureString(p);
|
||||
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
||||
p = p.replace(/"/g, '""');
|
||||
ou += node.quo + p + node.quo + node.sep;
|
||||
|
0
packages/node_modules/@node-red/nodes/core/storage/10-file.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/core/storage/10-file.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/20-inject.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/20-inject.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/21-debug.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/21-debug.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/25-catch.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/25-catch.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/25-status.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/25-status.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/60-link.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/60-link.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/90-comment.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/90-comment.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/98-unknown.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/common/98-unknown.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/10-function.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/10-function.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/10-switch.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/10-switch.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/15-change.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/15-change.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/16-range.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/16-range.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/80-template.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/80-template.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/89-delay.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/89-delay.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/89-trigger.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/89-trigger.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/90-exec.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/function/90-exec.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/messages.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/messages.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/05-tls.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/05-tls.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/06-httpproxy.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/06-httpproxy.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/10-mqtt.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/10-mqtt.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/21-httpin.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/21-httpin.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/21-httprequest.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/21-httprequest.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/22-websocket.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/22-websocket.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/31-tcpin.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/31-tcpin.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/32-udp.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/network/32-udp.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-CSV.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-CSV.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-HTML.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-HTML.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-JSON.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-JSON.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-XML.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-XML.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-YAML.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/parsers/70-YAML.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/sequence/17-split.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/sequence/17-split.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/sequence/18-sort.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/sequence/18-sort.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/sequence/19-batch.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/sequence/19-batch.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/storage/10-file.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/storage/10-file.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/storage/23-watch.html
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/de/storage/23-watch.html
vendored
Executable file → Normal file
@ -446,7 +446,9 @@
|
||||
"staticTopic": "Subscribe to single topic",
|
||||
"dynamicTopic": "Dynamic subscription",
|
||||
"auto-connect": "Connect automatically",
|
||||
"auto-mode-depreciated": "This option is depreciated. Please use the new auto-detect mode."
|
||||
"auto-mode-depreciated": "This option is depreciated. Please use the new auto-detect mode.",
|
||||
"none": "none",
|
||||
"other": "other"
|
||||
},
|
||||
"sections-label": {
|
||||
"birth-message": "Message sent on connection (birth message)",
|
||||
|
@ -446,7 +446,9 @@
|
||||
"staticTopic": "1つのトピックを購読",
|
||||
"dynamicTopic": "動的な購読",
|
||||
"auto-connect": "自動接続",
|
||||
"auto-mode-depreciated": "本オプションは非推奨になりました。新しい自動判定モードを使用してください。"
|
||||
"auto-mode-depreciated": "本オプションは非推奨になりました。新しい自動判定モードを使用してください。",
|
||||
"none": "なし",
|
||||
"other": "その他"
|
||||
},
|
||||
"sections-label": {
|
||||
"birth-message": "接続時の送信メッセージ(Birthメッセージ)",
|
||||
|
0
packages/node_modules/@node-red/nodes/locales/ko/messages.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/ko/messages.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/ru/messages.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/nodes/locales/ru/messages.json
vendored
Executable file → Normal file
@ -43,37 +43,40 @@ function load(disableNodePathScan) {
|
||||
return loadModuleFiles(modules);
|
||||
}
|
||||
|
||||
function splitPath(p) {
|
||||
return path.posix.normalize((p || '').replace(/\\/g, path.sep)).split(path.sep)
|
||||
}
|
||||
|
||||
function loadModuleTypeFiles(module, type) {
|
||||
const things = module[type];
|
||||
var first = true;
|
||||
var promises = [];
|
||||
for (var thingName in things) {
|
||||
let first = true;
|
||||
const promises = [];
|
||||
for (let thingName in things) {
|
||||
/* istanbul ignore else */
|
||||
if (things.hasOwnProperty(thingName)) {
|
||||
if (module.name != "node-red" && first) {
|
||||
// Check the module directory exists
|
||||
first = false;
|
||||
var fn = things[thingName].file;
|
||||
var parts = fn.split("/");
|
||||
var i = parts.length-1;
|
||||
for (;i>=0;i--) {
|
||||
if (parts[i] == "node_modules") {
|
||||
break;
|
||||
}
|
||||
let moduleFn = module.path
|
||||
const fn = things[thingName].file
|
||||
const parts = splitPath(fn)
|
||||
const nmi = parts.indexOf('node_modules')
|
||||
if(nmi > -1) {
|
||||
moduleFn = parts.slice(0,nmi+2).join(path.sep);
|
||||
}
|
||||
if (!moduleFn) {
|
||||
// shortcut - skip calling statSync on empty string
|
||||
break; // Module not found, don't attempt to load its nodes
|
||||
}
|
||||
var moduleFn = parts.slice(0,i+2).join("/");
|
||||
|
||||
try {
|
||||
var stat = fs.statSync(moduleFn);
|
||||
const stat = fs.statSync(moduleFn);
|
||||
} catch(err) {
|
||||
// Module not found, don't attempt to load its nodes
|
||||
break;
|
||||
break; // Module not found, don't attempt to load its nodes
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var promise;
|
||||
let promise;
|
||||
if (type === "nodes") {
|
||||
promise = loadNodeConfig(things[thingName]);
|
||||
} else if (type === "plugins") {
|
||||
@ -82,8 +85,7 @@ function loadModuleTypeFiles(module, type) {
|
||||
promises.push(
|
||||
promise.then(
|
||||
(function() {
|
||||
var m = module.name;
|
||||
var n = thingName;
|
||||
const n = thingName;
|
||||
return function(nodeSet) {
|
||||
things[n] = nodeSet;
|
||||
return nodeSet;
|
||||
@ -93,7 +95,6 @@ function loadModuleTypeFiles(module, type) {
|
||||
);
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +156,16 @@ function scanDirForNodesModules(dir,moduleName,package) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have found a package.json, this IS a node_module, lets see if it is a node-red node
|
||||
if (!isNodeRedModule && files.indexOf('package.json') > -1) {
|
||||
package = getPackageDetails(dir) // get package details
|
||||
if(package && package.isNodeRedModule) {
|
||||
isNodeRedModule = true
|
||||
files = ['package.json'] // shortcut the file scan
|
||||
}
|
||||
}
|
||||
|
||||
for (let i=0;i<files.length;i++) {
|
||||
let fn = files[i];
|
||||
if (!isNodeRedModule && /^@/.test(fn)) {
|
||||
|
@ -185,10 +185,17 @@ function loadNodeConfigs() {
|
||||
function addModule(module) {
|
||||
moduleNodes[module.name] = [];
|
||||
moduleConfigs[module.name] = module;
|
||||
// console.log("registry.js.addModule",module.name,"user?",module.user,"usedBy",module.usedBy,"dependencies",module.dependencies)
|
||||
for (var setName in module.nodes) {
|
||||
for (const setName in module.nodes) {
|
||||
if (module.nodes.hasOwnProperty(setName)) {
|
||||
var set = module.nodes[setName];
|
||||
const set = module.nodes[setName];
|
||||
if (!set.types) {
|
||||
const err = new Error("Set has no types")
|
||||
err.code = "set_has_no_types"
|
||||
err.details = {
|
||||
...set
|
||||
}
|
||||
set.err = err
|
||||
}
|
||||
moduleNodes[module.name].push(set.name);
|
||||
nodeList.push(set.id);
|
||||
if (!set.err) {
|
||||
|
@ -161,6 +161,8 @@ function start() {
|
||||
for (i=0;i<nodeErrors.length;i+=1) {
|
||||
if (nodeErrors[i].err.code === "type_already_registered") {
|
||||
log.warn("["+nodeErrors[i].id+"] "+log._("server.type-already-registered",{type:nodeErrors[i].err.details.type,module: nodeErrors[i].err.details.moduleA}));
|
||||
} else if (nodeErrors[i].err.code === "set_has_no_types") {
|
||||
log.warn("["+nodeErrors[i].id+"] "+log._("server.set-has-no-types", nodeErrors[i].err.details));
|
||||
} else {
|
||||
log.warn("["+nodeErrors[i].id+"] "+nodeErrors[i].err);
|
||||
}
|
||||
|
@ -373,6 +373,11 @@ Node.prototype.send = function(msg) {
|
||||
if (msg === null || typeof msg === "undefined") {
|
||||
return;
|
||||
} else if (!util.isArray(msg)) {
|
||||
// A single message has been passed in
|
||||
if (typeof msg !== 'object') {
|
||||
this.error(Log._("nodes.flow.non-message-returned", { type: typeof msg }));
|
||||
return
|
||||
}
|
||||
if (this._wire) {
|
||||
// A single message and a single wire on output 0
|
||||
// TODO: pre-load flows.get calls - cannot do in constructor
|
||||
@ -425,27 +430,31 @@ Node.prototype.send = function(msg) {
|
||||
for (k = 0; k < msgs.length; k++) {
|
||||
var m = msgs[k];
|
||||
if (m !== null && m !== undefined) {
|
||||
if (!m._msgid) {
|
||||
hasMissingIds = true;
|
||||
if (typeof m !== 'object') {
|
||||
this.error(Log._("nodes.flow.non-message-returned", { type: typeof m }));
|
||||
} else {
|
||||
if (!m._msgid) {
|
||||
hasMissingIds = true;
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (!sentMessageId) {
|
||||
sentMessageId = m._msgid;
|
||||
}
|
||||
sendEvents.push({
|
||||
msg: m,
|
||||
source: {
|
||||
id: this.id,
|
||||
node: this,
|
||||
port: i
|
||||
},
|
||||
destination: {
|
||||
id: wires[j],
|
||||
node: undefined
|
||||
},
|
||||
cloneMessage: msgSent
|
||||
});
|
||||
msgSent = true;
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (!sentMessageId) {
|
||||
sentMessageId = m._msgid;
|
||||
}
|
||||
sendEvents.push({
|
||||
msg: m,
|
||||
source: {
|
||||
id: this.id,
|
||||
node: this,
|
||||
port: i
|
||||
},
|
||||
destination: {
|
||||
id: wires[j],
|
||||
node: undefined
|
||||
},
|
||||
cloneMessage: msgSent
|
||||
});
|
||||
msgSent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ function runGitCommandWithSSHCommand(args,cwd,auth,emit) {
|
||||
commandEnv.GIT_SSH = path.join(__dirname,"node-red-ssh.sh");
|
||||
commandEnv.NODE_RED_KEY_FILE=auth.key_path;
|
||||
// GIT_SSH_COMMAND - added in git 2.3.0
|
||||
commandEnv.GIT_SSH_COMMAND = "ssh -i " + auth.key_path + " -F /dev/null";
|
||||
commandEnv.GIT_SSH_COMMAND = "ssh -i \"" + auth.key_path + "\" -F /dev/null";
|
||||
// console.log('commandEnv:', commandEnv);
|
||||
return runGitCommand(args,cwd,commandEnv,emit).then( result => {
|
||||
rs.close();
|
||||
|
0
packages/node_modules/@node-red/runtime/locales/de/runtime.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/runtime/locales/de/runtime.json
vendored
Executable file → Normal file
@ -20,6 +20,7 @@
|
||||
"errors-help": "Run with -v for details",
|
||||
"missing-modules": "Missing node modules:",
|
||||
"node-version-mismatch": "Node module cannot be loaded on this version. Requires: __version__ ",
|
||||
"set-has-no-types": "Set does not have any types. name: '__name__', module: '__module__', file: '__file__'",
|
||||
"type-already-registered": "'__type__' already registered by module __module__",
|
||||
"removing-modules": "Removing modules from config",
|
||||
"added-types": "Added node types:",
|
||||
@ -134,7 +135,8 @@
|
||||
"flow": {
|
||||
"unknown-type": "Unknown type: __type__",
|
||||
"missing-types": "missing types",
|
||||
"error-loop": "Message exceeded maximum number of catches"
|
||||
"error-loop": "Message exceeded maximum number of catches",
|
||||
"non-message-returned": "Node tried to send a message of type __type__"
|
||||
},
|
||||
"index": {
|
||||
"unrecognised-id": "Unrecognised id: __id__",
|
||||
|
0
packages/node_modules/@node-red/runtime/locales/ko/runtime.json
vendored
Executable file → Normal file
0
packages/node_modules/@node-red/runtime/locales/ko/runtime.json
vendored
Executable file → Normal file
@ -1717,6 +1717,24 @@ describe('change Node', function() {
|
||||
changeNode1.receive({topic:{foo:{bar:1}}, payload:"String"});
|
||||
});
|
||||
});
|
||||
it('moves the value of a message property object to itself', function(done) {
|
||||
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
helper.load(changeNode, flow, function() {
|
||||
var changeNode1 = helper.getNode("changeNode1");
|
||||
var helperNode1 = helper.getNode("helperNode1");
|
||||
helperNode1.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.equal("bar");
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
changeNode1.receive({payload:"bar"});
|
||||
});
|
||||
});
|
||||
it('moves the value of a message property object to a sub-property', function(done) {
|
||||
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.foo","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
|
@ -1529,7 +1529,7 @@ describe('HTTP Request Node', function() {
|
||||
msg.payload.headers.should.have.property('Content-Type').which.startWith('application/json');
|
||||
//msg.dynamicHeaderName should be present in headers with the value of msg.dynamicHeaderValue
|
||||
msg.payload.headers.should.have.property('dyn-header-name').which.startWith('dyn-header-value');
|
||||
//static (custom) header set in Flow UI should be present
|
||||
//static (custom) header set in Flow UI should be present
|
||||
msg.payload.headers.should.have.property('static-header-name').which.startWith('static-header-value');
|
||||
//msg.headers['location'] should be deleted because Flow UI "Location" header has a blank value
|
||||
//ensures headers with matching characters but different case are eliminated
|
||||
@ -2281,7 +2281,7 @@ describe('HTTP Request Node', function() {
|
||||
let port = testPort++
|
||||
|
||||
let server;
|
||||
|
||||
|
||||
before(function() {
|
||||
server = net.createServer(function (socket) {
|
||||
socket.write("HTTP/1.0 200\nContent-Type: text/plain\n\nHelloWorld")
|
||||
@ -2291,7 +2291,7 @@ describe('HTTP Request Node', function() {
|
||||
server.listen(port,'127.0.0.1', function(err) {
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
after(function() {
|
||||
server.close()
|
||||
});
|
||||
@ -2322,14 +2322,14 @@ describe('HTTP Request Node', function() {
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on('input', function(msg) {
|
||||
try{
|
||||
msg.payload.should.startWith(`RequestError: Parse Error:`)
|
||||
msg.payload.should.match(/RequestError: Parse Error/)
|
||||
done()
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
n1.receive({payload: 'foo'})
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -489,6 +489,39 @@ describe('MQTT Nodes', function () {
|
||||
}
|
||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should safely discard bad birth topic', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const baseTopic = nextTopic();
|
||||
const brokerOptions = {
|
||||
protocolVersion: 4,
|
||||
birthTopic: baseTopic + "#", // a publish topic should never have a wildcard
|
||||
birthPayload: "broker connected",
|
||||
birthQos: 2,
|
||||
}
|
||||
const options = {};
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null };
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
msg.should.have.a.property("error").type("object");
|
||||
msg.error.should.have.a.property("source").type("object");
|
||||
msg.error.source.should.have.a.property("id", mqttIn.id);
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
return true; //handled
|
||||
}
|
||||
options.expectMsg = null;
|
||||
try {
|
||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||
done()
|
||||
} catch(err) {
|
||||
done(e)
|
||||
}
|
||||
});
|
||||
itConditional('should publish close message', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
@ -646,12 +679,13 @@ function testSendRecv(brokerOptions, inNodeOptions, outNodeOptions, options, hoo
|
||||
const mqttBroker = helper.getNode(brokerOptions.id);
|
||||
const mqttIn = helper.getNode(nodes.mqtt_in.id);
|
||||
const mqttOut = helper.getNode(nodes.mqtt_out.id);
|
||||
let afterLoadHandled = false;
|
||||
let afterLoadHandled = false, finished = false;
|
||||
if (hooks.afterLoad) {
|
||||
afterLoadHandled = hooks.afterLoad(helperNode, mqttBroker, mqttIn, mqttOut)
|
||||
}
|
||||
if (!afterLoadHandled) {
|
||||
helperNode.on("input", function (msg) {
|
||||
finished = true
|
||||
try {
|
||||
compareMsgToExpected(msg, expectMsg);
|
||||
if (hooks.done) { hooks.done(); }
|
||||
@ -676,10 +710,12 @@ function testSendRecv(brokerOptions, inNodeOptions, outNodeOptions, options, hoo
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
if(finished) { return }
|
||||
if (hooks.done) { hooks.done(e); }
|
||||
else { throw e; }
|
||||
});
|
||||
} catch (err) {
|
||||
if(finished) { return }
|
||||
if (hooks.done) { hooks.done(err); }
|
||||
else { throw err; }
|
||||
}
|
||||
|
@ -693,19 +693,20 @@ describe('CSV node', function() {
|
||||
describe('json object to csv', function() {
|
||||
|
||||
it('should convert a simple object back to a csv', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e,f", wires:[["n2"]] },
|
||||
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e,f,g,h,i,j,k", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
// console.log("GOT",msg)
|
||||
try {
|
||||
msg.should.have.property('payload', '4,foo,true,,0,"Hello\nWorld"\n');
|
||||
msg.should.have.property('payload', '4,foo,true,,0,"Hello\nWorld",,,undefined,null,null\n');
|
||||
done();
|
||||
}
|
||||
catch(e) { done(e); }
|
||||
});
|
||||
var testJson = { e:0, d:1, b:"foo", c:true, a:4, f:"Hello\nWorld" };
|
||||
var testJson = { e:0, d:1, b:"foo", c:true, a:4, f:"Hello\nWorld", h:undefined, i:"undefined",j:null,k:"null" };
|
||||
n1.emit("input", {payload:testJson});
|
||||
});
|
||||
});
|
||||
@ -717,13 +718,14 @@ describe('CSV node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
// console.log("GOT",msg)
|
||||
try {
|
||||
msg.should.have.property('payload', '1,foo,"ba""r","di,ng"\n');
|
||||
msg.should.have.property('payload', '1,foo,"ba""r","di,ng",,undefined,null\n');
|
||||
done();
|
||||
}
|
||||
catch(e) { done(e); }
|
||||
});
|
||||
var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng" };
|
||||
var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng", e:undefined, f:"undefined", g:null,h:"null" };
|
||||
n1.emit("input", {payload:testJson});
|
||||
});
|
||||
});
|
||||
@ -764,6 +766,33 @@ describe('CSV node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle a template with quotes in the property names', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"", hdrout:"all", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('payload', 'a"a,b\'b\nA1,B1\nA2,B2\n');
|
||||
done();
|
||||
}
|
||||
catch(e) { done(e); }
|
||||
});
|
||||
var testJson = [
|
||||
{
|
||||
"a\"a": "A1",
|
||||
"b'b": "B1"
|
||||
},
|
||||
{
|
||||
"a\"a": "A2",
|
||||
"b'b": "B2"
|
||||
}
|
||||
]
|
||||
n1.emit("input", {payload:testJson});
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert an array of objects to a multi-line csv', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"a,d,c,b", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
|
@ -15,11 +15,14 @@
|
||||
**/
|
||||
|
||||
var fs = require("fs-extra");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
var should = require("should");
|
||||
var helper = require("node-red-node-test-helper");
|
||||
var watchNode = require("nr-test-utils").require("@node-red/nodes/core/storage/23-watch.js");
|
||||
|
||||
var arch = os.arch();
|
||||
var platform = os.platform();
|
||||
|
||||
describe('watch Node', function() {
|
||||
this.timeout(5000);
|
||||
@ -89,7 +92,10 @@ describe('watch Node', function() {
|
||||
msg.should.have.property('payload', result.payload);
|
||||
msg.should.have.property('type', result.type);
|
||||
if('size' in result) {
|
||||
msg.should.have.property('size', result.size);
|
||||
if (!((arch === "arm64") && (platform === "darwin"))) {
|
||||
// On OSX/ARM, two change events occur and first event do not reflect file size change. So ignore size field in the case.
|
||||
msg.should.have.property('size', result.size);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if(count === len) {
|
||||
|
@ -329,17 +329,36 @@ describe("red/nodes/registry/localfilesystem",function() {
|
||||
localfilesystem.init({nodesDir:[nodesDir2]});
|
||||
const nodeModule = localfilesystem.getModuleFiles();
|
||||
const loaded = Object.keys(nodeModule)
|
||||
loaded.should.have.a.property("length", 3)
|
||||
loaded.indexOf('@test/testnode').should.greaterThan(-1, "Should load @test/testnode")
|
||||
loaded.indexOf('lower-case').should.greaterThan(-1, "Should load lower-case")
|
||||
loaded.indexOf('@lowercase/lower-case2').should.greaterThan(-1, "Should load @lowercase/lower-case2")
|
||||
loaded.indexOf('testnode2').should.greaterThan(-1, "Should load testnode2")
|
||||
loaded.indexOf('test-theme2').should.greaterThan(-1, "Should load test-theme2")
|
||||
loaded.should.have.a.property("length", 5)
|
||||
|
||||
// scoped module with nodes in same dir as package.json
|
||||
nodeModule['@test/testnode'].should.have.a.property('name','@test/testnode');
|
||||
nodeModule['@test/testnode'].should.have.a.property('version','1.0.0');
|
||||
nodeModule['@test/testnode'].should.have.a.property('nodes');
|
||||
nodeModule['@test/testnode'].should.have.a.property('path');
|
||||
nodeModule['@test/testnode'].should.have.a.property('user', false);
|
||||
|
||||
// node-red module with nodes in sub dir
|
||||
nodeModule['@lowercase/lower-case2'].should.have.a.property('name','@lowercase/lower-case2');
|
||||
nodeModule['@lowercase/lower-case2'].should.have.a.property('version','2.0.0');
|
||||
nodeModule['@lowercase/lower-case2'].should.have.a.property('nodes');
|
||||
nodeModule['@lowercase/lower-case2'].nodes.should.have.a.property('lower-case');
|
||||
nodeModule['@lowercase/lower-case2'].should.have.a.property('path');
|
||||
nodeModule['@lowercase/lower-case2'].should.have.a.property('user', false);
|
||||
|
||||
// scoped module with nodes in sub dir
|
||||
nodeModule['lower-case'].should.have.a.property('name', 'lower-case');
|
||||
nodeModule['lower-case'].should.have.a.property('version','1.0.0');
|
||||
nodeModule['lower-case'].should.have.a.property('nodes');
|
||||
nodeModule['lower-case'].nodes.should.have.a.property('lower-case');
|
||||
nodeModule['lower-case'].should.have.a.property('path');
|
||||
nodeModule['lower-case'].should.have.a.property('user', false);
|
||||
|
||||
nodeModule['testnode2'].should.have.a.property('name','testnode2');
|
||||
nodeModule['testnode2'].should.have.a.property('version','1.0.0');
|
||||
nodeModule['testnode2'].should.have.a.property('nodes');
|
||||
|
@ -0,0 +1,26 @@
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('lower-case2',{
|
||||
category: 'function',
|
||||
color: '#a6bbcf',
|
||||
defaults: {
|
||||
name: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "file.png",
|
||||
label: function() {
|
||||
return this.name||"lower-case2";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-template-name="lower-case2">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="lower-case2">
|
||||
<p>A simple node that converts the message payloads into all lower-case2 characters</p>
|
||||
</script>
|
@ -0,0 +1,11 @@
|
||||
module.exports = function(RED) {
|
||||
function LowerCaseNode(config) {
|
||||
RED.nodes.createNode(this,config);
|
||||
var node = this;
|
||||
node.on('input', function(msg) {
|
||||
msg.payload = msg.payload.toLowerCase();
|
||||
node.send(msg);
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("lower-case2",LowerCaseNode);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name" : "@lowercase/lower-case2",
|
||||
"node-red" : {
|
||||
"nodes": {
|
||||
"lower-case": "lower-case2/lower-case.js"
|
||||
}
|
||||
},
|
||||
"version": "2.0.0"
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('lower-case',{
|
||||
category: 'function',
|
||||
color: '#a6bbcf',
|
||||
defaults: {
|
||||
name: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "file.png",
|
||||
label: function() {
|
||||
return this.name||"lower-case";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-template-name="lower-case">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="lower-case">
|
||||
<p>A simple node that converts the message payloads into all lower-case characters</p>
|
||||
</script>
|
@ -0,0 +1,11 @@
|
||||
module.exports = function(RED) {
|
||||
function LowerCaseNode(config) {
|
||||
RED.nodes.createNode(this,config);
|
||||
var node = this;
|
||||
node.on('input', function(msg) {
|
||||
msg.payload = msg.payload.toLowerCase();
|
||||
node.send(msg);
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("lower-case",LowerCaseNode);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name" : "lower-case",
|
||||
"node-red" : {
|
||||
"nodes": {
|
||||
"lower-case": "lower-case/lower-case.js"
|
||||
}
|
||||
},
|
||||
"version": "1.0.0"
|
||||
}
|
Loading…
Reference in New Issue
Block a user