diff --git a/packages/node_modules/@node-red/nodes/core/common/20-inject.html b/packages/node_modules/@node-red/nodes/core/common/20-inject.html
deleted file mode 100644
index f233c62fd..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/20-inject.html
+++ /dev/null
@@ -1,711 +0,0 @@
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/guide.html b/packages/node_modules/@node-red/nodes/core/common/guide.html
new file mode 100644
index 000000000..dfff21e3e
--- /dev/null
+++ b/packages/node_modules/@node-red/nodes/core/common/guide.html
@@ -0,0 +1,67 @@
+
+
+
+
+
+
diff --git a/packages/node_modules/@node-red/nodes/core/common/guide.js b/packages/node_modules/@node-red/nodes/core/common/guide.js
new file mode 100644
index 000000000..44802d135
--- /dev/null
+++ b/packages/node_modules/@node-red/nodes/core/common/guide.js
@@ -0,0 +1,25 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+// 2022 Modification Copyright - Defense Unicorns
+
+module.exports = function(RED) {
+ "use strict";
+ function GuideNode(n) {
+ RED.nodes.createNode(this,n);
+ }
+ RED.nodes.registerType("guide",GuideNode);
+}
diff --git a/packages/node_modules/@node-red/nodes/core/common/resource.html b/packages/node_modules/@node-red/nodes/core/common/resource.html
new file mode 100644
index 000000000..d4db2f931
--- /dev/null
+++ b/packages/node_modules/@node-red/nodes/core/common/resource.html
@@ -0,0 +1,67 @@
+
+
+
+
+
+
diff --git a/packages/node_modules/@node-red/nodes/core/common/resource.js b/packages/node_modules/@node-red/nodes/core/common/resource.js
new file mode 100644
index 000000000..180a600f2
--- /dev/null
+++ b/packages/node_modules/@node-red/nodes/core/common/resource.js
@@ -0,0 +1,25 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+// 2022 Modification Copyright - Defense Unicorns
+
+module.exports = function(RED) {
+ "use strict";
+ function ResourceNode(n) {
+ RED.nodes.createNode(this,n);
+ }
+ RED.nodes.registerType("resource",ResourceNode);
+}
diff --git a/packages/node_modules/@node-red/nodes/core/common/task.html b/packages/node_modules/@node-red/nodes/core/common/task.html
new file mode 100644
index 000000000..c1f8ebdac
--- /dev/null
+++ b/packages/node_modules/@node-red/nodes/core/common/task.html
@@ -0,0 +1,67 @@
+
+
+
+
+
+
diff --git a/packages/node_modules/@node-red/nodes/core/common/task.js b/packages/node_modules/@node-red/nodes/core/common/task.js
new file mode 100644
index 000000000..ce1c1410e
--- /dev/null
+++ b/packages/node_modules/@node-red/nodes/core/common/task.js
@@ -0,0 +1,25 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+// 2022 Modification Copyright - Defense Unicorns
+
+module.exports = function(RED) {
+ "use strict";
+ function TaskNode(n) {
+ RED.nodes.createNode(this,n);
+ }
+ RED.nodes.registerType("task",TaskNode);
+}
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.html b/packages/node_modules/@node-red/nodes/core/function/10-function.html
deleted file mode 100644
index a1ed14f6d..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/10-function.html
+++ /dev/null
@@ -1,611 +0,0 @@
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.js b/packages/node_modules/@node-red/nodes/core/function/10-function.js
deleted file mode 100644
index b84ee8571..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/10-function.js
+++ /dev/null
@@ -1,510 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- var util = require("util");
- var vm = require("vm");
- var acorn = require("acorn");
- var acornWalk = require("acorn-walk");
-
- function sendResults(node,send,_msgid,msgs,cloneFirstMessage) {
- if (msgs == null) {
- return;
- } else if (!util.isArray(msgs)) {
- msgs = [msgs];
- }
- var msgCount = 0;
- for (var m=0; m0) {
- send(msgs);
- }
- }
-
- function createVMOpt(node, kind) {
- var opt = {
- filename: 'Function node'+kind+':'+node.id+(node.name?' ['+node.name+']':''), // filename for stack traces
- displayErrors: true
- // Using the following options causes node 4/6 to not include the line number
- // in the stack output. So don't use them.
- // lineOffset: -11, // line number offset to be used for stack traces
- // columnOffset: 0, // column number offset to be used for stack traces
- };
- return opt;
- }
-
- function updateErrorInfo(err) {
- if (err.stack) {
- var stack = err.stack.toString();
- var m = /^([^:]+):([^:]+):(\d+).*/.exec(stack);
- if (m) {
- var line = parseInt(m[3]) -1;
- var kind = "body:";
- if (/setup/.exec(m[1])) {
- kind = "setup:";
- }
- if (/cleanup/.exec(m[1])) {
- kind = "cleanup:";
- }
- err.message += " ("+kind+"line "+line+")";
- }
- }
- }
-
- function FunctionNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- node.name = n.name;
- node.func = n.func;
- node.outputs = n.outputs;
- node.ini = n.initialize ? n.initialize.trim() : "";
- node.fin = n.finalize ? n.finalize.trim() : "";
- node.libs = n.libs || [];
-
- if (RED.settings.functionExternalModules === false && node.libs.length > 0) {
- throw new Error(RED._("function.error.externalModuleNotAllowed"));
- }
-
-
-
- var functionText = "var results = null;"+
- "results = (async function(msg,__send__,__done__){ "+
- "var __msgid__ = msg._msgid;"+
- "var node = {"+
- "id:__node__.id,"+
- "name:__node__.name,"+
- "path:__node__.path,"+
- "outputCount:__node__.outputCount,"+
- "log:__node__.log,"+
- "error:__node__.error,"+
- "warn:__node__.warn,"+
- "debug:__node__.debug,"+
- "trace:__node__.trace,"+
- "on:__node__.on,"+
- "status:__node__.status,"+
- "send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+
- "done:__done__"+
- "};\n"+
- node.func+"\n"+
- "})(msg,__send__,__done__);";
-
- var handleNodeDoneCall = true;
-
- // Check to see if the Function appears to call `node.done()`. If so,
- // we will assume it is well written and does actually call node.done().
- // Otherwise, we will call node.done() after the function returns regardless.
- if (/node\.done\s*\(\s*\)/.test(functionText)) {
- // We have spotted the code contains `node.done`. It could be in a comment
- // so need to do the extra work to parse the AST and examine it properly.
- acornWalk.simple(acorn.parse(functionText,{ecmaVersion: "latest"} ), {
- CallExpression(astNode) {
- if (astNode.callee && astNode.callee.object) {
- if (astNode.callee.object.name === "node" && astNode.callee.property.name === "done") {
- handleNodeDoneCall = false;
- }
- }
- }
- })
- }
-
- var finScript = null;
- var finOpt = null;
- node.topic = n.topic;
- node.outstandingTimers = [];
- node.outstandingIntervals = [];
- node.clearStatus = false;
-
- var sandbox = {
- console:console,
- util:util,
- Buffer:Buffer,
- Date: Date,
- RED: {
- util: RED.util
- },
- __node__: {
- id: node.id,
- name: node.name,
- path: node._path,
- outputCount: node.outputs,
- log: function() {
- node.log.apply(node, arguments);
- },
- error: function() {
- node.error.apply(node, arguments);
- },
- warn: function() {
- node.warn.apply(node, arguments);
- },
- debug: function() {
- node.debug.apply(node, arguments);
- },
- trace: function() {
- node.trace.apply(node, arguments);
- },
- send: function(send, id, msgs, cloneMsg) {
- sendResults(node, send, id, msgs, cloneMsg);
- },
- on: function() {
- if (arguments[0] === "input") {
- throw new Error(RED._("function.error.inputListener"));
- }
- node.on.apply(node, arguments);
- },
- status: function() {
- node.clearStatus = true;
- node.status.apply(node, arguments);
- }
- },
- context: {
- set: function() {
- node.context().set.apply(node,arguments);
- },
- get: function() {
- return node.context().get.apply(node,arguments);
- },
- keys: function() {
- return node.context().keys.apply(node,arguments);
- },
- get global() {
- return node.context().global;
- },
- get flow() {
- return node.context().flow;
- }
- },
- flow: {
- set: function() {
- node.context().flow.set.apply(node,arguments);
- },
- get: function() {
- return node.context().flow.get.apply(node,arguments);
- },
- keys: function() {
- return node.context().flow.keys.apply(node,arguments);
- }
- },
- global: {
- set: function() {
- node.context().global.set.apply(node,arguments);
- },
- get: function() {
- return node.context().global.get.apply(node,arguments);
- },
- keys: function() {
- return node.context().global.keys.apply(node,arguments);
- }
- },
- env: {
- get: function(envVar) {
- return RED.util.getSetting(node, envVar);
- }
- },
- setTimeout: function () {
- var func = arguments[0];
- var timerId;
- arguments[0] = function() {
- sandbox.clearTimeout(timerId);
- try {
- func.apply(node,arguments);
- } catch(err) {
- node.error(err,{});
- }
- };
- timerId = setTimeout.apply(node,arguments);
- node.outstandingTimers.push(timerId);
- return timerId;
- },
- clearTimeout: function(id) {
- clearTimeout(id);
- var index = node.outstandingTimers.indexOf(id);
- if (index > -1) {
- node.outstandingTimers.splice(index,1);
- }
- },
- setInterval: function() {
- var func = arguments[0];
- var timerId;
- arguments[0] = function() {
- try {
- func.apply(node,arguments);
- } catch(err) {
- node.error(err,{});
- }
- };
- timerId = setInterval.apply(node,arguments);
- node.outstandingIntervals.push(timerId);
- return timerId;
- },
- clearInterval: function(id) {
- clearInterval(id);
- var index = node.outstandingIntervals.indexOf(id);
- if (index > -1) {
- node.outstandingIntervals.splice(index,1);
- }
- }
- };
- if (util.hasOwnProperty('promisify')) {
- sandbox.setTimeout[util.promisify.custom] = function(after, value) {
- return new Promise(function(resolve, reject) {
- sandbox.setTimeout(function(){ resolve(value); }, after);
- });
- };
- sandbox.promisify = util.promisify;
- }
- const moduleLoadPromises = [];
-
- if (node.hasOwnProperty("libs")) {
- let moduleErrors = false;
- var modules = node.libs;
- modules.forEach(module => {
- var vname = module.hasOwnProperty("var") ? module.var : null;
- if (vname && (vname !== "")) {
- if (sandbox.hasOwnProperty(vname) || vname === 'node') {
- node.error(RED._("function.error.moduleNameError",{name:vname}))
- moduleErrors = true;
- return;
- }
- sandbox[vname] = null;
- var spec = module.module;
- if (spec && (spec !== "")) {
- moduleLoadPromises.push(RED.import(module.module).then(lib => {
- sandbox[vname] = lib.default;
- }).catch(err => {
- node.error(RED._("function.error.moduleLoadError",{module:module.spec, error:err.toString()}))
- throw err;
- }));
- }
- }
- });
- if (moduleErrors) {
- throw new Error(RED._("function.error.externalModuleLoadError"));
- }
- }
- const RESOLVING = 0;
- const RESOLVED = 1;
- const ERROR = 2;
- var state = RESOLVING;
- var messages = [];
- var processMessage = (() => {});
-
- node.on("input", function(msg,send,done) {
- if(state === RESOLVING) {
- messages.push({msg:msg, send:send, done:done});
- }
- else if(state === RESOLVED) {
- processMessage(msg, send, done);
- }
- });
- Promise.all(moduleLoadPromises).then(() => {
- var context = vm.createContext(sandbox);
- try {
- var iniScript = null;
- var iniOpt = null;
- if (node.ini && (node.ini !== "")) {
- var iniText = `
- (async function(__send__) {
- var node = {
- id:__node__.id,
- name:__node__.name,
- path:__node__.path,
- outputCount:__node__.outputCount,
- log:__node__.log,
- error:__node__.error,
- warn:__node__.warn,
- debug:__node__.debug,
- trace:__node__.trace,
- status:__node__.status,
- send: function(msgs, cloneMsg) {
- __node__.send(__send__, RED.util.generateId(), msgs, cloneMsg);
- }
- };
- `+ node.ini +`
- })(__initSend__);`;
- iniOpt = createVMOpt(node, " setup");
- iniScript = new vm.Script(iniText, iniOpt);
- }
- node.script = vm.createScript(functionText, createVMOpt(node, ""));
- if (node.fin && (node.fin !== "")) {
- var finText = `(function () {
- var node = {
- id:__node__.id,
- name:__node__.name,
- path:__node__.path,
- outputCount:__node__.outputCount,
- log:__node__.log,
- error:__node__.error,
- warn:__node__.warn,
- debug:__node__.debug,
- trace:__node__.trace,
- status:__node__.status,
- send: function(msgs, cloneMsg) {
- __node__.error("Cannot send from close function");
- }
- };
- `+node.fin +`
- })();`;
- finOpt = createVMOpt(node, " cleanup");
- finScript = new vm.Script(finText, finOpt);
- }
- var promise = Promise.resolve();
- if (iniScript) {
- context.__initSend__ = function(msgs) { node.send(msgs); };
- promise = iniScript.runInContext(context, iniOpt);
- }
-
- processMessage = function (msg, send, done) {
- var start = process.hrtime();
- context.msg = msg;
- context.__send__ = send;
- context.__done__ = done;
-
- node.script.runInContext(context);
- context.results.then(function(results) {
- sendResults(node,send,msg._msgid,results,false);
- if (handleNodeDoneCall) {
- done();
- }
-
- var duration = process.hrtime(start);
- var converted = Math.floor((duration[0] * 1e9 + duration[1])/10000)/100;
- node.metric("duration", msg, converted);
- if (process.env.NODE_RED_FUNCTION_TIME) {
- node.status({fill:"yellow",shape:"dot",text:""+converted});
- }
- }).catch(err => {
- if ((typeof err === "object") && err.hasOwnProperty("stack")) {
- //remove unwanted part
- var index = err.stack.search(/\n\s*at ContextifyScript.Script.runInContext/);
- err.stack = err.stack.slice(0, index).split('\n').slice(0,-1).join('\n');
- var stack = err.stack.split(/\r?\n/);
-
- //store the error in msg to be used in flows
- msg.error = err;
-
- var line = 0;
- var errorMessage;
- if (stack.length > 0) {
- while (line < stack.length && stack[line].indexOf("ReferenceError") !== 0) {
- line++;
- }
-
- if (line < stack.length) {
- errorMessage = stack[line];
- var m = /:(\d+):(\d+)$/.exec(stack[line+1]);
- if (m) {
- var lineno = Number(m[1])-1;
- var cha = m[2];
- errorMessage += " (line "+lineno+", col "+cha+")";
- }
- }
- }
- if (!errorMessage) {
- errorMessage = err.toString();
- }
- done(errorMessage);
- }
- else if (typeof err === "string") {
- done(err);
- }
- else {
- done(JSON.stringify(err));
- }
- });
- }
-
- node.on("close", function() {
- if (finScript) {
- try {
- finScript.runInContext(context, finOpt);
- }
- catch (err) {
- node.error(err);
- }
- }
- while (node.outstandingTimers.length > 0) {
- clearTimeout(node.outstandingTimers.pop());
- }
- while (node.outstandingIntervals.length > 0) {
- clearInterval(node.outstandingIntervals.pop());
- }
- if (node.clearStatus) {
- node.status({});
- }
- });
-
- promise.then(function (v) {
- var msgs = messages;
- messages = [];
- while (msgs.length > 0) {
- msgs.forEach(function (s) {
- processMessage(s.msg, s.send, s.done);
- });
- msgs = messages;
- messages = [];
- }
- state = RESOLVED;
- }).catch((error) => {
- messages = [];
- state = ERROR;
- node.error(error);
- });
-
- }
- catch(err) {
- // eg SyntaxError - which v8 doesn't include line number information
- // so we can't do better than this
- updateErrorInfo(err);
- node.error(err);
- }
- }).catch(err => {
- node.error(RED._("function.error.externalModuleLoadError"));
- });
- }
- RED.nodes.registerType("function",FunctionNode, {
- dynamicModuleList: "libs",
- settings: {
- functionExternalModules: { value: true, exportable: true }
- }
- });
- RED.library.register("functions");
-};
diff --git a/packages/node_modules/@node-red/nodes/core/function/89-delay.html b/packages/node_modules/@node-red/nodes/core/function/89-delay.html
deleted file mode 100644
index 8ee404924..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/89-delay.html
+++ /dev/null
@@ -1,284 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/90-exec.js b/packages/node_modules/@node-red/nodes/core/function/90-exec.js
deleted file mode 100644
index 2ae9947dd..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/90-exec.js
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var spawn = require('child_process').spawn;
- var exec = require('child_process').exec;
- var fs = require('fs');
- var isUtf8 = require('is-utf8');
-
- function ExecNode(n) {
- RED.nodes.createNode(this,n);
- this.cmd = (n.command || "").trim();
- if (n.addpay === undefined) { n.addpay = true; }
- this.addpay = n.addpay;
- if (this.addpay === true) {
- this.addpay = "payload";
- }
- this.append = (n.append || "").trim();
- this.useSpawn = (n.useSpawn == "true");
- this.timer = Number(n.timer || 0)*1000;
- this.activeProcesses = {};
- this.oldrc = (n.oldrc || false).toString();
- this.execOpt = {encoding:'binary', maxBuffer:RED.settings.execMaxBufferSize||10000000, windowsHide: (n.winHide === true)};
- this.spawnOpt = {windowsHide: (n.winHide === true) }
- var node = this;
-
- if (process.platform === 'linux' && fs.existsSync('/bin/bash')) { node.execOpt.shell = '/bin/bash'; }
-
- var cleanup = function(p) {
- node.activeProcesses[p].kill();
- //node.status({fill:"red",shape:"dot",text:"timeout"});
- //node.error("Exec node timeout");
- }
-
- this.on("input", function(msg, nodeSend, nodeDone) {
- if (msg.hasOwnProperty("kill")) {
- if (typeof msg.kill !== "string" || msg.kill.length === 0 || !msg.kill.toUpperCase().startsWith("SIG") ) { msg.kill = "SIGTERM"; }
- if (msg.hasOwnProperty("pid")) {
- if (node.activeProcesses.hasOwnProperty(msg.pid) ) {
- node.activeProcesses[msg.pid].kill(msg.kill.toUpperCase());
- node.status({fill:"red",shape:"dot",text:"killed"});
- }
- }
- else {
- if (Object.keys(node.activeProcesses).length === 1) {
- node.activeProcesses[Object.keys(node.activeProcesses)[0]].kill(msg.kill.toUpperCase());
- node.status({fill:"red",shape:"dot",text:"killed"});
- }
- }
- nodeDone();
- }
- else {
- var child;
- // make the extra args into an array
- // then prepend with the msg.payload
- var arg = node.cmd;
- if (node.addpay) {
- var value = RED.util.getMessageProperty(msg, node.addpay);
- if (value !== undefined) {
- arg += " " + value;
- }
- }
- if (node.append.trim() !== "") { arg += " " + node.append; }
- if (this.useSpawn === true) {
- // slice whole line by spaces and removes any quotes since spawn can't handle them
- arg = arg.match(/(?:[^\s"]+|"[^"]*")+/g).map((a) => {
- if (/^".*"$/.test(a)) {
- return a.slice(1,-1)
- } else {
- return a
- }
- });
- var cmd = arg.shift();
- /* istanbul ignore else */
- node.debug(cmd+" ["+arg+"]");
- child = spawn(cmd,arg,node.spawnOpt);
- node.status({fill:"blue",shape:"dot",text:"pid:"+child.pid});
- var unknownCommand = (child.pid === undefined);
- if (node.timer !== 0) {
- child.tout = setTimeout(function() { cleanup(child.pid); }, node.timer);
- }
- node.activeProcesses[child.pid] = child;
- child.stdout.on('data', function (data) {
- if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
- // console.log('[exec] stdout: ' + data,child.pid);
- if (isUtf8(data)) { msg.payload = data.toString(); }
- else { msg.payload = data; }
- nodeSend([RED.util.cloneMessage(msg),null,null]);
- }
- });
- child.stderr.on('data', function (data) {
- if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
- if (isUtf8(data)) { msg.payload = data.toString(); }
- else { msg.payload = Buffer.from(data); }
- nodeSend([null,RED.util.cloneMessage(msg),null]);
- }
- });
- child.on('close', function (code,signal) {
- if (unknownCommand || (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null)) {
- delete node.activeProcesses[child.pid];
- if (child.tout) { clearTimeout(child.tout); }
- msg.payload = code;
- if (node.oldrc === "false") {
- msg.payload = {code:code};
- if (signal) { msg.payload.signal = signal; }
- }
- if (code === 0) { node.status({}); }
- if (code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
- else if (code < 0) { node.status({fill:"red",shape:"dot",text:"rc:"+code}); }
- else { node.status({fill:"yellow",shape:"dot",text:"rc:"+code}); }
- nodeSend([null,null,RED.util.cloneMessage(msg)]);
- }
- nodeDone();
- });
- child.on('error', function (code) {
- if (child.tout) { clearTimeout(child.tout); }
- delete node.activeProcesses[child.pid];
- if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
- node.error(code,RED.util.cloneMessage(msg));
- }
- });
- }
- else {
- /* istanbul ignore else */
- node.debug(arg);
- child = exec(arg, node.execOpt, function (error, stdout, stderr) {
- var msg2, msg3;
- delete msg.payload;
- if (stderr) {
- msg2 = RED.util.cloneMessage(msg);
- msg2.payload = stderr;
- }
- msg.payload = Buffer.from(stdout,"binary");
- if (isUtf8(msg.payload)) { msg.payload = msg.payload.toString(); }
- node.status({});
- //console.log('[exec] stdout: ' + stdout);
- //console.log('[exec] stderr: ' + stderr);
- if (error !== null) {
- msg3 = RED.util.cloneMessage(msg);
- msg3.payload = {code:error.code, message:error.message};
- if (error.signal) { msg3.payload.signal = error.signal; }
- if (error.code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
- else { node.status({fill:"red",shape:"dot",text:"error:"+error.code}); }
- node.debug('error:' + error);
- }
- else if (node.oldrc === "false") {
- msg3 = RED.util.cloneMessage(msg);
- msg3.payload = {code:0};
- }
- if (!msg3) { node.status({}); }
- else {
- msg.rc = msg3.payload;
- if (msg2) { msg2.rc = msg3.payload; }
- }
- nodeSend([msg,msg2,msg3]);
- if (child.tout) { clearTimeout(child.tout); }
- delete node.activeProcesses[child.pid];
- nodeDone();
- });
- node.status({fill:"blue",shape:"dot",text:"pid:"+child.pid});
- child.on('error',function() {});
- if (node.timer !== 0) {
- child.tout = setTimeout(function() { cleanup(child.pid); }, node.timer);
- }
- node.activeProcesses[child.pid] = child;
- }
- }
- });
-
- this.on('close',function() {
- for (var pid in node.activeProcesses) {
- /* istanbul ignore else */
- if (node.activeProcesses.hasOwnProperty(pid)) {
- if (node.activeProcesses[pid].tout) { clearTimeout(node.activeProcesses[pid].tout); }
- // console.log("KILLING",pid);
- var process = node.activeProcesses[pid];
- node.activeProcesses[pid] = null;
- process.kill();
- }
- }
- node.activeProcesses = {};
- node.status({});
- });
- }
- RED.nodes.registerType("exec",ExecNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/rbe.js b/packages/node_modules/@node-red/nodes/core/function/rbe.js
deleted file mode 100644
index eb526a441..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/rbe.js
+++ /dev/null
@@ -1,97 +0,0 @@
-
-module.exports = function(RED) {
- "use strict";
- function RbeNode(n) {
- RED.nodes.createNode(this,n);
- this.func = n.func || "rbe";
- this.gap = n.gap || "0";
- this.start = n.start || '';
- this.inout = n.inout || "out";
- this.pc = false;
- if (this.gap.substr(-1) === "%") {
- this.pc = true;
- this.gap = parseFloat(this.gap);
- }
- this.g = this.gap;
- this.property = n.property || "payload";
- this.topi = n.topi || "topic";
- this.septopics = true;
- if (n.septopics !== undefined && n.septopics === false) {
- this.septopics = false;
- }
-
- var node = this;
-
- node.previous = {};
- this.on("input",function(msg) {
- var topic;
- try {
- topic = RED.util.getMessageProperty(msg,node.topi);
- }
- catch(e) { }
- if (msg.hasOwnProperty("reset")) {
- if (node.septopics && topic && (typeof topic === "string") && (topic !== "")) {
- delete node.previous[msg.topic];
- }
- else { node.previous = {}; }
- }
- var value = RED.util.getMessageProperty(msg,node.property);
- if (value !== undefined) {
- var t = "_no_topic";
- if (node.septopics) { t = topic || t; }
- if ((this.func === "rbe") || (this.func === "rbei")) {
- var doSend = (this.func !== "rbei") || (node.previous.hasOwnProperty(t)) || false;
- if (typeof(value) === "object") {
- if (typeof(node.previous[t]) !== "object") { node.previous[t] = {}; }
- if (!RED.util.compareObjects(value, node.previous[t])) {
- node.previous[t] = RED.util.cloneMessage(value);
- if (doSend) { node.send(msg); }
- }
- }
- else {
- if (value !== node.previous[t]) {
- node.previous[t] = RED.util.cloneMessage(value);
- if (doSend) { node.send(msg); }
- }
- }
- }
- else {
- var n = parseFloat(value);
- if (!isNaN(n)) {
- if ((typeof node.previous[t] === 'undefined') && (this.func === "narrowband" || this.func === "narrowbandEq")) {
- if (node.start === '') { node.previous[t] = n; }
- else { node.previous[t] = node.start; }
- }
- if (node.pc) { node.gap = Math.abs(node.previous[t] * node.g / 100) || 0; }
- else { node.gap = Number(node.gap); }
- if ((node.previous[t] === undefined) && (node.func === "narrowbandEq")) { node.previous[t] = n; }
- if (node.previous[t] === undefined) { node.previous[t] = n - node.gap - 1; }
- if (Math.abs(n - node.previous[t]) === node.gap) {
- if ((this.func === "deadbandEq")||(this.func === "narrowband")) {
- if (node.inout === "out") { node.previous[t] = n; }
- node.send(msg);
- }
- }
- else if (Math.abs(n - node.previous[t]) > node.gap) {
- if (this.func === "deadband" || this.func === "deadbandEq") {
- if (node.inout === "out") { node.previous[t] = n; }
- node.send(msg);
- }
- }
- else if (Math.abs(n - node.previous[t]) < node.gap) {
- if ((this.func === "narrowband")||(this.func === "narrowbandEq")) {
- if (node.inout === "out") { node.previous[t] = n; }
- node.send(msg);
- }
- }
- if (node.inout === "in") { node.previous[t] = n; }
- }
- else {
- node.warn(RED._("rbe.warn.nonumber"));
- }
- }
- } // ignore msg with no payload property.
- });
- }
- RED.nodes.registerType("rbe",RbeNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js
deleted file mode 100644
index bf677b490..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js
+++ /dev/null
@@ -1,675 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- const got = require("got");
- const {CookieJar} = require("tough-cookie");
- const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent');
- const FormData = require('form-data');
- const { v4: uuid } = require('uuid');
- const crypto = require('crypto');
- const URL = require("url").URL
- var mustache = require("mustache");
- var querystring = require("querystring");
- var cookie = require("cookie");
- var hashSum = require("hash-sum");
-
-
- // Cache a reference to the existing https.request function
- // so we can compare later to see if an old agent-base instance
- // has been required.
- // This is generally okay as the core nodes are required before
- // any contrib nodes. Where it will fail is if the agent-base module
- // is required via the settings file or outside of Node-RED before it
- // is started.
- // If there are other modules that patch the function, they will get undone
- // as well. Not much we can do about that right now. Patching core
- // functions is bad.
- const HTTPS_MODULE = require("https");
- const HTTPS_REQUEST = HTTPS_MODULE.request;
-
- function checkNodeAgentPatch() {
- if (HTTPS_MODULE.request !== HTTPS_REQUEST && HTTPS_MODULE.request.length === 2) {
- RED.log.warn(`
-
----------------------------------------------------------------------
-Patched https.request function detected. This will break the
-HTTP Request node. The original code has now been restored.
-
-This is likely caused by a contrib node including an old version of
-the 'agent-base@<5.0.0' module.
-
-You can identify what node is at fault by running:
- npm list agent-base
-in your Node-RED user directory (${RED.settings.userDir}).
----------------------------------------------------------------------
-`);
- HTTPS_MODULE.request = HTTPS_REQUEST
- }
- }
-
- function HTTPRequest(n) {
- RED.nodes.createNode(this,n);
- checkNodeAgentPatch();
- var node = this;
- var nodeUrl = n.url;
- var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1;
- var nodeMethod = n.method || "GET";
- var paytoqs = false;
- var paytobody = false;
- var redirectList = [];
- var sendErrorsToCatch = n.senderr;
-
- var nodeHTTPPersistent = n["persist"];
- if (n.tls) {
- var tlsNode = RED.nodes.getNode(n.tls);
- }
- this.ret = n.ret || "txt";
- this.authType = n.authType || "basic";
- if (RED.settings.httpRequestTimeout) { this.reqTimeout = parseInt(RED.settings.httpRequestTimeout) || 120000; }
- else { this.reqTimeout = 120000; }
-
- if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; }
- else if (n.paytoqs === "body") { paytobody = true; }
-
-
- var prox, noprox;
- if (process.env.http_proxy) { prox = process.env.http_proxy; }
- if (process.env.HTTP_PROXY) { prox = process.env.HTTP_PROXY; }
- if (process.env.no_proxy) { noprox = process.env.no_proxy.split(","); }
- if (process.env.NO_PROXY) { noprox = process.env.NO_PROXY.split(","); }
-
- var proxyConfig = null;
- if (n.proxy) {
- proxyConfig = RED.nodes.getNode(n.proxy);
- prox = proxyConfig.url;
- noprox = proxyConfig.noproxy;
- }
-
- let timingLog = false;
- if (RED.settings.hasOwnProperty("httpRequestTimingLog")) {
- timingLog = RED.settings.httpRequestTimingLog;
- }
-
- this.on("input",function(msg,nodeSend,nodeDone) {
- checkNodeAgentPatch();
- //reset redirectList on each request
- redirectList = [];
- var preRequestTimestamp = process.hrtime();
- node.status({fill:"blue",shape:"dot",text:"httpin.status.requesting"});
- var url = nodeUrl || msg.url;
- if (msg.url && nodeUrl && (nodeUrl !== msg.url)) { // revert change below when warning is finally removed
- node.warn(RED._("common.errors.nooverride"));
- }
-
- if (isTemplatedUrl) {
- url = mustache.render(nodeUrl,msg);
- }
- if (!url) {
- node.error(RED._("httpin.errors.no-url"),msg);
- nodeDone();
- return;
- }
-
-
- // url must start http:// or https:// so assume http:// if not set
- if (url.indexOf("://") !== -1 && url.indexOf("http") !== 0) {
- node.warn(RED._("httpin.errors.invalid-transport"));
- node.status({fill:"red",shape:"ring",text:"httpin.errors.invalid-transport"});
- nodeDone();
- return;
- }
- if (!((url.indexOf("http://") === 0) || (url.indexOf("https://") === 0))) {
- if (tlsNode) {
- url = "https://"+url;
- } else {
- url = "http://"+url;
- }
- }
-
- // The Request module used in Node-RED 1.x was tolerant of query strings that
- // were partially encoded. For example - "?a=hello%20there&b=20%"
- // The GOT module doesn't like that.
- // The following is an attempt to normalise the url to ensure it is properly
- // encoded. We cannot just encode it directly as we don't want any valid
- // encoded entity to end up doubly encoded.
- if (url.indexOf("?") > -1) {
- // Only do this if there is a query string to deal with
- const [hostPath, ...queryString] = url.split("?")
- const query = queryString.join("?");
- if (query) {
- // Look for any instance of % not followed by two hex chars.
- // Replace any we find with %25.
- const escapedQueryString = query.replace(/(%.?.?)/g, function(v) {
- if (/^%[a-f0-9]{2}/i.test(v)) {
- return v;
- }
- return v.replace(/%/,"%25")
- })
- url = hostPath+"?"+escapedQueryString;
- }
- }
-
- var method = nodeMethod.toUpperCase() || "GET";
- if (msg.method && n.method && (n.method !== "use")) { // warn if override option not set
- node.warn(RED._("common.errors.nooverride"));
- }
- if (msg.method && n.method && (n.method === "use")) {
- method = msg.method.toUpperCase(); // use the msg parameter
- }
-
- // var isHttps = (/^https/i.test(url));
-
- var opts = {};
- // set defaultport, else when using HttpsProxyAgent, it's defaultPort of 443 will be used :(.
- // Had to remove this to get http->https redirect to work
- // opts.defaultPort = isHttps?443:80;
- opts.timeout = node.reqTimeout;
- opts.throwHttpErrors = false;
- // TODO: add UI option to auto decompress. Setting to false for 1.x compatibility
- opts.decompress = false;
- opts.method = method;
- opts.headers = {};
- opts.retry = 0;
- opts.responseType = 'buffer';
- opts.maxRedirects = 21;
- opts.cookieJar = new CookieJar();
- opts.ignoreInvalidCookies = true;
- opts.forever = nodeHTTPPersistent;
- if (msg.requestTimeout !== undefined) {
- if (isNaN(msg.requestTimeout)) {
- node.warn(RED._("httpin.errors.timeout-isnan"));
- } else if (msg.requestTimeout < 1) {
- node.warn(RED._("httpin.errors.timeout-isnegative"));
- } else {
- opts.timeout = msg.requestTimeout;
- }
- }
- const originalHeaderMap = {};
-
- opts.hooks = {
- beforeRequest: [
- options => {
- // Whilst HTTP headers are meant to be case-insensitive,
- // in the real world, there are servers that aren't so compliant.
- // GOT will lower case all headers given a chance, so we need
- // to restore the case of any headers the user has set.
- Object.keys(options.headers).forEach(h => {
- if (originalHeaderMap[h] && originalHeaderMap[h] !== h) {
- options.headers[originalHeaderMap[h]] = options.headers[h];
- delete options.headers[h];
- }
- })
- }
- ],
- beforeRedirect: [
- (options, response) => {
- let redirectInfo = {
- location: response.headers.location
- }
- if (response.headers.hasOwnProperty('set-cookie')) {
- redirectInfo.cookies = extractCookies(response.headers['set-cookie']);
- }
- redirectList.push(redirectInfo)
- }
- ]
- }
-
- var ctSet = "Content-Type"; // set default camel case
- var clSet = "Content-Length";
- if (msg.headers) {
- if (msg.headers.hasOwnProperty('x-node-red-request-node')) {
- var headerHash = msg.headers['x-node-red-request-node'];
- delete msg.headers['x-node-red-request-node'];
- var hash = hashSum(msg.headers);
- if (hash === headerHash) {
- delete msg.headers;
- }
- }
- if (msg.headers) {
- for (var v in msg.headers) {
- if (msg.headers.hasOwnProperty(v)) {
- var name = v.toLowerCase();
- if (name !== "content-type" && name !== "content-length") {
- // only normalise the known headers used later in this
- // function. Otherwise leave them alone.
- name = v;
- }
- else if (name === 'content-type') { ctSet = v; }
- else { clSet = v; }
- opts.headers[name] = msg.headers[v];
- }
- }
- }
- }
-
- if (msg.hasOwnProperty('followRedirects')) {
- opts.followRedirect = !!msg.followRedirects;
- }
-
- if (opts.headers.hasOwnProperty('cookie')) {
- var cookies = cookie.parse(opts.headers.cookie, {decode:String});
- for (var name in cookies) {
- opts.cookieJar.setCookieSync(cookie.serialize(name, cookies[name], {encode:String}), url, {ignoreError: true});
- }
- delete opts.headers.cookie;
- }
- if (msg.cookies) {
- for (var name in msg.cookies) {
- if (msg.cookies.hasOwnProperty(name)) {
- if (msg.cookies[name] === null || msg.cookies[name].value === null) {
- // This case clears a cookie for HTTP In/Response nodes.
- // Ignore for this node.
- } else if (typeof msg.cookies[name] === 'object') {
- if(msg.cookies[name].encode === false){
- // If the encode option is false, the value is not encoded.
- opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name].value, {encode: String}), url, {ignoreError: true});
- } else {
- // The value is encoded by encodeURIComponent().
- opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name].value), url, {ignoreError: true});
- }
- } else {
- opts.cookieJar.setCookieSync(cookie.serialize(name, msg.cookies[name]), url, {ignoreError: true});
- }
- }
- }
- }
- var parsedURL = new URL(url)
- this.credentials = this.credentials || {}
- if (parsedURL.username && !this.credentials.user) {
- this.credentials.user = parsedURL.username
- }
- if (parsedURL.password && !this.credentials.password) {
- this.credentials.password = parsedURL.password
- }
- if (Object.keys(this.credentials).length != 0) {
- if (this.authType === "basic") {
- // Workaround for https://github.com/sindresorhus/got/issues/1169 (fixed in got v12)
- // var cred = ""
- if (this.credentials.user || this.credentials.password) {
- // cred = `${this.credentials.user}:${this.credentials.password}`;
- if (this.credentials.user === undefined) { this.credentials.user = ""}
- if (this.credentials.password === undefined) { this.credentials.password = ""}
- opts.headers.Authorization = "Basic " + Buffer.from(`${this.credentials.user}:${this.credentials.password}`).toString("base64");
- }
- // build own basic auth header
- // opts.headers.Authorization = "Basic " + Buffer.from(cred).toString("base64");
- } else if (this.authType === "digest") {
- let digestCreds = this.credentials;
- let sentCreds = false;
- opts.hooks.afterResponse = [(response, retry) => {
- if (response.statusCode === 401) {
- if (sentCreds) {
- return response
- }
- const requestUrl = new URL(response.request.requestUrl);
- const options = response.request.options;
- const normalisedHeaders = {};
- Object.keys(response.headers).forEach(k => {
- normalisedHeaders[k.toLowerCase()] = response.headers[k]
- })
- if (normalisedHeaders['www-authenticate']) {
- let authHeader = buildDigestHeader(digestCreds.user,digestCreds.password, options.method, requestUrl.pathname, normalisedHeaders['www-authenticate'])
- options.headers.Authorization = authHeader;
- }
- sentCreds = true;
- return retry(options);
- }
- return response
- }];
- } else if (this.authType === "bearer") {
- opts.headers.Authorization = `Bearer ${this.credentials.password||""}`
- }
- }
- var payload = null;
-
-
- 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 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);
- } else if (typeof val === 'object' && val.hasOwnProperty('value')) {
- formData.append(opt,val.value,val.options || {});
- } else {
- formData.append(opt,JSON.stringify(val));
- }
- }
- }
- }
- // GOT will only set the content-type header with the correct boundary
- // if the header isn't set. So we delete it here, for GOT to reset it.
- delete opts.headers['content-type'];
- opts.body = formData;
- } else {
- if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
- payload = msg.payload;
- } else if (typeof msg.payload == "number") {
- payload = msg.payload+"";
- } else {
- if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') {
- payload = querystring.stringify(msg.payload);
- } else {
- payload = JSON.stringify(msg.payload);
- if (opts.headers['content-type'] == null) {
- opts.headers[ctSet] = "application/json";
- }
- }
- }
- if (opts.headers['content-length'] == null) {
- if (Buffer.isBuffer(payload)) {
- opts.headers[clSet] = payload.length;
- } else {
- opts.headers[clSet] = Buffer.byteLength(payload);
- }
- }
- opts.body = payload;
- }
- }
-
-
- if (method == 'GET' && typeof msg.payload !== "undefined" && paytoqs) {
- if (typeof msg.payload === "object") {
- try {
- if (url.indexOf("?") !== -1) {
- url += (url.endsWith("?")?"":"&") + querystring.stringify(msg.payload);
- } else {
- url += "?" + querystring.stringify(msg.payload);
- }
- } catch(err) {
-
- node.error(RED._("httpin.errors.invalid-payload"),msg);
- nodeDone();
- return;
- }
- } else {
-
- node.error(RED._("httpin.errors.invalid-payload"),msg);
- nodeDone();
- return;
- }
- } else if ( method == "GET" && typeof msg.payload !== "undefined" && paytobody) {
- opts.allowGetBody = true;
- if (typeof msg.payload === "object") {
- opts.body = JSON.stringify(msg.payload);
- } else if (typeof msg.payload == "number") {
- opts.body = msg.payload+"";
- } else if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
- opts.body = msg.payload;
- }
- }
-
- // revert to user supplied Capitalisation if needed.
- if (opts.headers.hasOwnProperty('content-type') && (ctSet !== 'content-type')) {
- opts.headers[ctSet] = opts.headers['content-type'];
- delete opts.headers['content-type'];
- }
- if (opts.headers.hasOwnProperty('content-length') && (clSet !== 'content-length')) {
- opts.headers[clSet] = opts.headers['content-length'];
- delete opts.headers['content-length'];
- }
-
- var noproxy;
- if (noprox) {
- for (var i = 0; i < noprox.length; i += 1) {
- if (url.indexOf(noprox[i]) !== -1) { noproxy=true; }
- }
- }
- if (prox && !noproxy) {
- var match = prox.match(/^(https?:\/\/)?(.+)?:([0-9]+)?/i);
- if (match) {
- let proxyAgent;
- let proxyURL = new URL(prox);
- //set username/password to null to stop empty creds header
- let proxyOptions = {
- proxy: {
- protocol: proxyURL.protocol,
- hostname: proxyURL.hostname,
- port: proxyURL.port,
- username: null,
- password: null
- },
- maxFreeSockets: 256,
- maxSockets: 256,
- keepAlive: true
- }
- if (proxyConfig && proxyConfig.credentials) {
- let proxyUsername = proxyConfig.credentials.username || '';
- let proxyPassword = proxyConfig.credentials.password || '';
- if (proxyUsername || proxyPassword) {
- proxyOptions.proxy.username = proxyUsername;
- proxyOptions.proxy.password = proxyPassword;
- }
- } else if (proxyURL.username || proxyURL.password){
- proxyOptions.proxy.username = proxyURL.username;
- proxyOptions.proxy.password = proxyURL.password;
- }
- //need both incase of http -> https redirect
- opts.agent = {
- http: new HttpProxyAgent(proxyOptions),
- https: new HttpsProxyAgent(proxyOptions)
- };
-
- } else {
- node.warn("Bad proxy url: "+ prox);
- }
- }
- if (tlsNode) {
- opts.https = {};
- tlsNode.addTLSOptions(opts.https);
- if (opts.https.ca) {
- opts.https.certificateAuthority = opts.https.ca;
- delete opts.https.ca;
- }
- if (opts.https.cert) {
- opts.https.certificate = opts.https.cert;
- delete opts.https.cert;
- }
- } else {
- if (msg.hasOwnProperty('rejectUnauthorized')) {
- opts.https = { rejectUnauthorized: msg.rejectUnauthorized };
- }
- }
-
- // Now we have established all of our own headers, take a snapshot
- // of their case so we can restore it prior to the request being sent.
- if (opts.headers) {
- Object.keys(opts.headers).forEach(h => {
- originalHeaderMap[h.toLowerCase()] = h
- })
- }
- got(url,opts).then(res => {
- msg.statusCode = res.statusCode;
- msg.headers = res.headers;
- msg.responseUrl = res.url;
- msg.payload = res.body;
- msg.redirectList = redirectList;
- msg.retry = 0;
-
- if (msg.headers.hasOwnProperty('set-cookie')) {
- msg.responseCookies = extractCookies(msg.headers['set-cookie']);
- }
- msg.headers['x-node-red-request-node'] = hashSum(msg.headers);
- // msg.url = url; // revert when warning above finally removed
- if (node.metric()) {
- // Calculate request time
- var diff = process.hrtime(preRequestTimestamp);
- var ms = diff[0] * 1e3 + diff[1] * 1e-6;
- var metricRequestDurationMillis = ms.toFixed(3);
- node.metric("duration.millis", msg, metricRequestDurationMillis);
- if (res.client && res.client.bytesRead) {
- node.metric("size.bytes", msg, res.client.bytesRead);
- }
- if (timingLog) {
- emitTimingMetricLog(res.timings, msg);
- }
- }
-
- // Convert the payload to the required return type
- if (node.ret !== "bin") {
- msg.payload = msg.payload.toString('utf8'); // txt
-
- if (node.ret === "obj") {
- try { msg.payload = JSON.parse(msg.payload); } // obj
- catch(e) { node.warn(RED._("httpin.errors.json-error")); }
- }
- }
- node.status({});
- nodeSend(msg);
- nodeDone();
- }).catch(err => {
- // Pre 2.1, any errors would be sent to both Catch node and sent on as normal.
- // This is not ideal but is the legacy behaviour of the node.
- // 2.1 adds the 'senderr' option, if set to true, will *only* send errors
- // to Catch nodes. If false, it still does both behaviours.
- // TODO: 3.0 - make it one or the other.
-
- if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
- node.error(RED._("common.notification.errors.no-response"), msg);
- node.status({fill:"red", shape:"ring", text:"common.notification.errors.no-response"});
- } else {
- node.error(err,msg);
- node.status({fill:"red", shape:"ring", text:err.code});
- }
- msg.payload = err.toString() + " : " + url;
- msg.statusCode = err.code || (err.response?err.response.statusCode:undefined);
- if (node.metric() && timingLog) {
- emitTimingMetricLog(err.timings, msg);
- }
- if (!sendErrorsToCatch) {
- nodeSend(msg);
- }
- nodeDone();
- });
- });
-
- this.on("close",function() {
- node.status({});
- });
-
- function emitTimingMetricLog(timings, msg) {
- const props = [
- "start",
- "socket",
- "lookup",
- "connect",
- "secureConnect",
- "upload",
- "response",
- "end",
- "error",
- "abort"
- ];
- if (timings) {
- props.forEach(p => {
- if (timings[p]) {
- node.metric(`timings.${p}`, msg, timings[p]);
- }
- });
- }
- }
-
- function extractCookies(setCookie) {
- var cookies = {};
- setCookie.forEach(function(c) {
- var parsedCookie = cookie.parse(c);
- var eq_idx = c.indexOf('=');
- var key = c.substr(0, eq_idx).trim()
- parsedCookie.value = parsedCookie[key];
- delete parsedCookie[key];
- cookies[key] = parsedCookie;
- });
- return cookies;
- }
- }
-
- RED.nodes.registerType("http request",HTTPRequest,{
- credentials: {
- user: {type:"text"},
- password: {type: "password"}
- }
- });
-
- const md5 = (value) => { return crypto.createHash('md5').update(value).digest('hex') }
-
- function ha1Compute(algorithm, user, realm, pass, nonce, cnonce) {
- /**
- * RFC 2617: handle both MD5 and MD5-sess algorithms.
- *
- * If the algorithm directive's value is "MD5" or unspecified, then HA1 is
- * HA1=MD5(username:realm:password)
- * If the algorithm directive's value is "MD5-sess", then HA1 is
- * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
- */
- var ha1 = md5(user + ':' + realm + ':' + pass)
- if (algorithm && algorithm.toLowerCase() === 'md5-sess') {
- return md5(ha1 + ':' + nonce + ':' + cnonce)
- } else {
- return ha1
- }
- }
-
-
- function buildDigestHeader(user, pass, method, path, authHeader) {
- var challenge = {}
- var re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi
- for (;;) {
- var match = re.exec(authHeader)
- if (!match) {
- break
- }
- challenge[match[1]] = match[2] || match[3]
- }
- var qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth'
- var nc = qop && '00000001'
- var cnonce = qop && uuid().replace(/-/g, '')
- var ha1 = ha1Compute(challenge.algorithm, user, challenge.realm, pass, challenge.nonce, cnonce)
- var ha2 = md5(method + ':' + path)
- var digestResponse = qop
- ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2)
- : md5(ha1 + ':' + challenge.nonce + ':' + ha2)
- var authValues = {
- username: user,
- realm: challenge.realm,
- nonce: challenge.nonce,
- uri: path,
- qop: qop,
- response: digestResponse,
- nc: nc,
- cnonce: cnonce,
- algorithm: challenge.algorithm,
- opaque: challenge.opaque
- }
-
- authHeader = []
- for (var k in authValues) {
- if (authValues[k]) {
- if (k === 'qop' || k === 'nc' || k === 'algorithm') {
- authHeader.push(k + '=' + authValues[k])
- } else {
- authHeader.push(k + '="' + authValues[k] + '"')
- }
- }
- }
- authHeader = 'Digest ' + authHeader.join(', ')
- return authHeader
- }
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/22-websocket.html b/packages/node_modules/@node-red/nodes/core/network/22-websocket.html
deleted file mode 100644
index a7b54d72f..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/22-websocket.html
+++ /dev/null
@@ -1,292 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/22-websocket.js b/packages/node_modules/@node-red/nodes/core/network/22-websocket.js
deleted file mode 100644
index ed4c93b09..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/22-websocket.js
+++ /dev/null
@@ -1,423 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var ws = require("ws");
- var inspect = require("util").inspect;
- var url = require("url");
- var HttpsProxyAgent = require('https-proxy-agent');
-
-
- var serverUpgradeAdded = false;
- function handleServerUpgrade(request, socket, head) {
- const pathname = url.parse(request.url).pathname;
- if (listenerNodes.hasOwnProperty(pathname)) {
- listenerNodes[pathname].server.handleUpgrade(request, socket, head, function done(ws) {
- listenerNodes[pathname].server.emit('connection', ws, request);
- });
- } else {
- // Don't destroy the socket as other listeners may want to handle the
- // event.
- }
- }
- var listenerNodes = {};
- var activeListenerNodes = 0;
-
-
- // A node red node that sets up a local websocket server
- function WebSocketListenerNode(n) {
- // Create a RED node
- RED.nodes.createNode(this,n);
- var node = this;
-
- // Store local copies of the node configuration (as defined in the .html)
- node.path = n.path;
- if (typeof n.subprotocol === "string") {
- // Split the string on comma and trim each result
- node.subprotocol = n.subprotocol.split(",").map(v => v.trim())
- } else {
- node.subprotocol = [];
- }
- node.wholemsg = (n.wholemsg === "true");
-
- node._inputNodes = []; // collection of nodes that want to receive events
- node._clients = {};
- // match absolute url
- node.isServer = !/^ws{1,2}:\/\//i.test(node.path);
- node.closing = false;
- node.tls = n.tls;
-
- if (n.hb) {
- var heartbeat = parseInt(n.hb);
- if (heartbeat > 0) {
- node.heartbeat = heartbeat * 1000;
- }
- }
-
- function startconn() { // Connect to remote endpoint
- node.tout = null;
- var prox, noprox;
- if (process.env.http_proxy) { prox = process.env.http_proxy; }
- if (process.env.HTTP_PROXY) { prox = process.env.HTTP_PROXY; }
- if (process.env.no_proxy) { noprox = process.env.no_proxy.split(","); }
- if (process.env.NO_PROXY) { noprox = process.env.NO_PROXY.split(","); }
-
- var noproxy = false;
- if (noprox) {
- for (var i in noprox) {
- if (node.path.indexOf(noprox[i].trim()) !== -1) { noproxy=true; }
- }
- }
-
- var agent = undefined;
- if (prox && !noproxy) {
- agent = new HttpsProxyAgent(prox);
- }
-
- var options = {};
- if (agent) {
- options.agent = agent;
- }
- if (node.tls) {
- var tlsNode = RED.nodes.getNode(node.tls);
- if (tlsNode) {
- tlsNode.addTLSOptions(options);
- }
- }
- var socket = new ws(node.path,node.subprotocol,options);
- socket.setMaxListeners(0);
- node.server = socket; // keep for closing
- handleConnection(socket);
- }
-
- function handleConnection(/*socket*/socket) {
- var id = RED.util.generateId();
- socket.nrId = id;
- socket.nrPendingHeartbeat = false;
- if (node.isServer) {
- node._clients[id] = socket;
- node.emit('opened',{count:Object.keys(node._clients).length,id:id});
- }
- socket.on('open',function() {
- if (!node.isServer) {
- if (node.heartbeat) {
- clearInterval(node.heartbeatInterval);
- node.heartbeatInterval = setInterval(function() {
- if (socket.nrPendingHeartbeat) {
- // No pong received
- socket.terminate();
- socket.nrErrorHandler(new Error("timeout"));
- return;
- }
- socket.nrPendingHeartbeat = true;
- try {
- socket.ping();
- } catch(err) {}
- },node.heartbeat);
- }
- node.emit('opened',{count:'',id:id});
- }
- });
- socket.on('close',function() {
- clearInterval(node.heartbeatInterval);
- if (node.isServer) {
- delete node._clients[id];
- node.emit('closed',{count:Object.keys(node._clients).length,id:id});
- } else {
- node.emit('closed',{count:'',id:id});
- }
- if (!node.closing && !node.isServer) {
- clearTimeout(node.tout);
- node.tout = setTimeout(function() { startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
- }
- });
- socket.on('message',function(data,flags) {
- node.handleEvent(id,socket,'message',data,flags);
- });
- socket.nrErrorHandler = function(err) {
- clearInterval(node.heartbeatInterval);
- node.emit('erro',{err:err,id:id});
- if (!node.closing && !node.isServer) {
- clearTimeout(node.tout);
- node.tout = setTimeout(function() { startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
- }
- }
- socket.on('error',socket.nrErrorHandler);
- socket.on('ping', function() {
- socket.nrPendingHeartbeat = false;
- })
- socket.on('pong', function() {
- socket.nrPendingHeartbeat = false;
- })
- }
-
- if (node.isServer) {
- activeListenerNodes++;
- if (!serverUpgradeAdded) {
- RED.server.on('upgrade', handleServerUpgrade);
- serverUpgradeAdded = true
- }
-
- var path = RED.settings.httpNodeRoot || "/";
- path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path);
- node.fullPath = path;
-
- if (listenerNodes.hasOwnProperty(path)) {
- node.error(RED._("websocket.errors.duplicate-path",{path: node.path}));
- return;
- }
- listenerNodes[node.fullPath] = node;
- var serverOptions = {
- noServer: true
- }
- if (RED.settings.webSocketNodeVerifyClient) {
- serverOptions.verifyClient = RED.settings.webSocketNodeVerifyClient;
- }
- // Create a WebSocket Server
- node.server = new ws.Server(serverOptions);
- node.server.setMaxListeners(0);
- node.server.on('connection', handleConnection);
- // Not adding server-initiated heartbeats yet
- // node.heartbeatInterval = setInterval(function() {
- // node.server.clients.forEach(function(ws) {
- // if (ws.nrPendingHeartbeat) {
- // // No pong received
- // ws.terminate();
- // ws.nrErrorHandler(new Error("timeout"));
- // return;
- // }
- // ws.nrPendingHeartbeat = true;
- // ws.ping();
- // });
- // })
- }
- else {
- node.closing = false;
- startconn(); // start outbound connection
- }
-
- node.on("close", function() {
- if (node.heartbeatInterval) {
- clearInterval(node.heartbeatInterval);
- }
- if (node.isServer) {
- delete listenerNodes[node.fullPath];
- node.server.close();
- node._inputNodes = [];
- activeListenerNodes--;
- // if (activeListenerNodes === 0 && serverUpgradeAdded) {
- // RED.server.removeListener('upgrade', handleServerUpgrade);
- // serverUpgradeAdded = false;
- // }
- }
- else {
- node.closing = true;
- node.server.close();
- if (node.tout) {
- clearTimeout(node.tout);
- node.tout = null;
- }
- }
- });
- }
- RED.nodes.registerType("websocket-listener",WebSocketListenerNode);
- RED.nodes.registerType("websocket-client",WebSocketListenerNode);
-
- WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler) {
- this._inputNodes.push(handler);
- }
-
- WebSocketListenerNode.prototype.removeInputNode = function(/*Node*/handler) {
- this._inputNodes.forEach(function(node, i, inputNodes) {
- if (node === handler) {
- inputNodes.splice(i, 1);
- }
- });
- }
-
- WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags) {
- var msg;
- if (this.wholemsg) {
- try {
- msg = JSON.parse(data);
- if (typeof msg !== "object" && !Array.isArray(msg) && (msg !== null)) {
- msg = { payload:msg };
- }
- }
- catch(err) {
- msg = { payload:data };
- }
- } else {
- msg = {
- payload:data
- };
- }
- msg._session = {type:"websocket",id:id};
- for (var i = 0; i < this._inputNodes.length; i++) {
- this._inputNodes[i].send(msg);
- }
- }
-
- WebSocketListenerNode.prototype.broadcast = function(data) {
- if (this.isServer) {
- for (let client in this._clients) {
- if (this._clients.hasOwnProperty(client)) {
- try {
- this._clients[client].send(data);
- } catch(err) {
- this.warn(RED._("websocket.errors.send-error")+" "+client+" "+err.toString())
- }
- }
- }
- }
- else {
- try {
- this.server.send(data);
- } catch(err) {
- this.warn(RED._("websocket.errors.send-error")+" "+err.toString())
- }
- }
- }
-
- WebSocketListenerNode.prototype.reply = function(id,data) {
- var session = this._clients[id];
- if (session) {
- try {
- session.send(data);
- }
- catch(e) { // swallow any errors
- }
- }
- }
-
- function WebSocketInNode(n) {
- RED.nodes.createNode(this,n);
- this.server = (n.client)?n.client:n.server;
- var node = this;
- this.serverConfig = RED.nodes.getNode(this.server);
- if (this.serverConfig) {
- this.serverConfig.registerInputNode(this);
- // TODO: nls
- this.serverConfig.on('opened', function(event) {
- node.status({
- fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count}),
- event:"connect",
- _session: {type:"websocket",id:event.id}
- });
- });
- this.serverConfig.on('erro', function(event) {
- node.status({
- fill:"red",shape:"ring",text:"common.status.error",
- event:"error",
- _session: {type:"websocket",id:event.id}
- });
- });
- this.serverConfig.on('closed', function(event) {
- var status;
- if (event.count > 0) {
- status = {fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count})};
- } else {
- status = {fill:"red",shape:"ring",text:"common.status.disconnected"};
- }
- status.event = "disconnect";
- status._session = {type:"websocket",id:event.id}
- node.status(status);
- });
- } else {
- this.error(RED._("websocket.errors.missing-conf"));
- }
- this.on('close', function() {
- if (node.serverConfig) {
- node.serverConfig.removeInputNode(node);
- }
- node.status({});
- });
- }
- RED.nodes.registerType("websocket in",WebSocketInNode);
-
- function WebSocketOutNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- this.server = (n.client)?n.client:n.server;
- this.serverConfig = RED.nodes.getNode(this.server);
- if (!this.serverConfig) {
- return this.error(RED._("websocket.errors.missing-conf"));
- }
- else {
- // TODO: nls
- this.serverConfig.on('opened', function(event) {
- node.status({
- fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count}),
- event:"connect",
- _session: {type:"websocket",id:event.id}
- });
- });
- this.serverConfig.on('erro', function(event) {
- node.status({
- fill:"red",shape:"ring",text:"common.status.error",
- event:"error",
- _session: {type:"websocket",id:event.id}
- })
- });
- this.serverConfig.on('closed', function(event) {
- var status;
- if (event.count > 0) {
- status = {fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count})};
- } else {
- status = {fill:"red",shape:"ring",text:"common.status.disconnected"};
- }
- status.event = "disconnect";
- status._session = {type:"websocket",id:event.id}
- node.status(status);
- });
- }
- this.on("input", function(msg, nodeSend, nodeDone) {
- var payload;
- if (this.serverConfig.wholemsg) {
- var sess;
- if (msg._session) { sess = JSON.stringify(msg._session); }
- delete msg._session;
- payload = JSON.stringify(msg);
- if (sess) { msg._session = JSON.parse(sess); }
- }
- else if (msg.hasOwnProperty("payload")) {
- if (!Buffer.isBuffer(msg.payload)) { // if it's not a buffer make sure it's a string.
- payload = RED.util.ensureString(msg.payload);
- }
- else {
- payload = msg.payload;
- }
- }
- if (payload) {
- if (msg._session && msg._session.type == "websocket") {
- node.serverConfig.reply(msg._session.id,payload);
- } else {
- node.serverConfig.broadcast(payload,function(error) {
- if (!!error) {
- node.warn(RED._("websocket.errors.send-error")+inspect(error));
- }
- });
- }
- }
- nodeDone();
- });
- this.on('close', function() {
- node.status({});
- });
- }
- RED.nodes.registerType("websocket out",WebSocketOutNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html
deleted file mode 100644
index 97c8eb4d7..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html
+++ /dev/null
@@ -1,383 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
deleted file mode 100644
index 24e6abf7e..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
+++ /dev/null
@@ -1,852 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- let reconnectTime = RED.settings.socketReconnectTime || 10000;
- let socketTimeout = RED.settings.socketTimeout || null;
- const msgQueueSize = RED.settings.tcpMsgQueueSize || 1000;
- const Denque = require('denque');
- const net = require('net');
- const tls = require('tls');
-
- let connectionPool = {};
-
- function normalizeConnectArgs(listArgs) {
- const args = net._normalizeArgs(listArgs);
- const options = args[0];
- const cb = args[1];
-
- // If args[0] was options, then normalize dealt with it.
- // If args[0] is port, or args[0], args[1] is host, port, we need to
- // find the options and merge them in, normalize's options has only
- // the host/port/path args that it knows about, not the tls options.
- // This means that options.host overrides a host arg.
- if (listArgs[1] !== null && typeof listArgs[1] === 'object') {
- ObjectAssign(options, listArgs[1]);
- } else if (listArgs[2] !== null && typeof listArgs[2] === 'object') {
- ObjectAssign(options, listArgs[2]);
- }
-
- return cb ? [options, cb] : [options];
- }
-
- function getAllowUnauthorized() {
- const allowUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0';
-
- if (allowUnauthorized) {
- process.emitWarning(
- 'Setting the NODE_TLS_REJECT_UNAUTHORIZED ' +
- 'environment variable to \'0\' makes TLS connections ' +
- 'and HTTPS requests insecure by disabling ' +
- 'certificate verification.');
- }
- return allowUnauthorized;
- }
-
- /**
- * Enqueue `item` in `queue`
- * @param {Denque} queue - Queue
- * @param {*} item - Item to enqueue
- * @private
- * @returns {Denque} `queue`
- */
- const enqueue = (queue, item) => {
- // drop msgs from front of queue if size is going to be exceeded
- if (queue.length === msgQueueSize) { queue.shift(); }
- queue.push(item);
- return queue;
- };
-
- /**
- * Shifts item off front of queue
- * @param {Deque} queue - Queue
- * @private
- * @returns {*} Item previously at front of queue
- */
- const dequeue = queue => queue.shift();
-
- function TcpIn(n) {
- RED.nodes.createNode(this,n);
- this.host = n.host;
- this.port = n.port * 1;
- this.topic = n.topic;
- this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/
- this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */
- this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
- this.base64 = n.base64;
- this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
- this.closing = false;
- this.connected = false;
- var node = this;
- var count = 0;
- if (n.tls) { var tlsNode = RED.nodes.getNode(n.tls); }
-
- if (!node.server) {
- var buffer = null;
- var client;
- var reconnectTimeout;
- var end = false;
- var setupTcpClient = function() {
- node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
- node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
- var id = RED.util.generateId();
- var connOpts = {host: node.host};
- if (n.tls) {
- var connOpts = tlsNode.addTLSOptions({host: node.host});
- client = tls.connect(node.port, connOpts, function() {
- buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
- node.connected = true;
- node.log(RED._("status.connected", {host: node.host, port: node.port}));
- node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
- });
- }
- else {
- client = net.connect(node.port, node.host, function() {
- buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
- node.connected = true;
- node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
- node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
- });
- }
- client.setKeepAlive(true, 120000);
- connectionPool[id] = client;
-
- client.on('data', function (data) {
- if (node.datatype != 'buffer') {
- data = data.toString(node.datatype);
- }
- if (node.stream) {
- var msg;
- if ((node.datatype) === "utf8" && node.newline !== "") {
- buffer = buffer+data;
- var parts = buffer.split(node.newline);
- for (var i = 0; i 0)) {
- var msg = {topic:node.topic, payload:buffer};
- msg._session = {type:"tcp",id:id};
- if (buffer.length !== 0) {
- end = true; // only ask for fast re-connect if we actually got something
- node.send(msg);
- }
- buffer = null;
- }
- });
- client.on('close', function() {
- delete connectionPool[id];
- node.connected = false;
- node.status({fill:"red",shape:"ring",text:"common.status.disconnected",_session:{type:"tcp",id:id}});
- if (!node.closing) {
- if (end) { // if we were asked to close then try to reconnect once very quick.
- end = false;
- reconnectTimeout = setTimeout(setupTcpClient, 20);
- }
- else {
- node.log(RED._("tcpin.errors.connection-lost",{host:node.host,port:node.port}));
- reconnectTimeout = setTimeout(setupTcpClient, reconnectTime);
- }
- } else {
- if (node.doneClose) { node.doneClose(); }
- }
- });
- client.on('error', function(err) {
- node.log(err);
- });
- }
- setupTcpClient();
-
- this.on('close', function(done) {
- node.doneClose = done;
- this.closing = true;
- if (client) { client.destroy(); }
- clearTimeout(reconnectTimeout);
- if (!node.connected) { done(); }
- });
- }
- else {
- let srv = net;
- let connOpts;
- if (n.tls) {
- srv = tls;
- connOpts = tlsNode.addTLSOptions({});
- }
- var server = srv.createServer(connOpts, function (socket) {
- socket.setKeepAlive(true,120000);
- if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
- var id = RED.util.generateId();
- var fromi;
- var fromp;
- connectionPool[id] = socket;
- count++;
- node.status({
- text:RED._("tcpin.status.connections",{count:count}),
- event:"connect",
- ip:socket.remoteAddress,
- port:socket.remotePort,
- _session: {type:"tcp",id:id}
- });
-
- var buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
- socket.on('data', function (data) {
- if (node.datatype != 'buffer') {
- data = data.toString(node.datatype);
- }
- if (node.stream) {
- var msg;
- if ((typeof data) === "string" && node.newline !== "") {
- buffer = buffer+data;
- var parts = buffer.split(node.newline);
- for (var i = 0; i 0) {
- var msg = {topic:node.topic, payload:buffer, ip:fromi, port:fromp};
- msg._session = {type:"tcp",id:id};
- node.send(msg);
- }
- buffer = null;
- }
- });
- socket.on('timeout', function() {
- node.log(RED._("tcpin.errors.timeout",{port:node.port}));
- socket.end();
- });
- socket.on('close', function() {
- delete connectionPool[id];
- count--;
- node.status({
- text:RED._("tcpin.status.connections",{count:count}),
- event:"disconnect",
- ip:socket.remoteAddress,
- port:socket.remotePort,
- _session: {type:"tcp",id:id}
-
- });
- });
- socket.on('error',function(err) {
- node.log(err);
- });
- });
-
- server.on('error', function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- }
- });
-
- server.listen(node.port, function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- } else {
- node.log(RED._("tcpin.status.listening-port",{port:node.port}));
- node.on('close', function() {
- for (var c in connectionPool) {
- if (connectionPool.hasOwnProperty(c)) {
- connectionPool[c].end();
- connectionPool[c].unref();
- }
- }
- node.closing = true;
- server.close();
- node.log(RED._("tcpin.status.stopped-listening",{port:node.port}));
- });
- }
- });
- }
- }
- RED.nodes.registerType("tcp in",TcpIn);
-
-
- function TcpOut(n) {
- RED.nodes.createNode(this,n);
- this.host = n.host;
- this.port = n.port * 1;
- this.base64 = n.base64;
- this.doend = n.end || false;
- this.beserver = n.beserver;
- this.name = n.name;
- this.closing = false;
- this.connected = false;
- var node = this;
- if (n.tls) { var tlsNode = RED.nodes.getNode(n.tls); }
-
- if (!node.beserver || node.beserver == "client") {
- var reconnectTimeout;
- var client = null;
- var end = false;
-
- var setupTcpClient = function() {
- node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
- node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
- if (n.tls) {
- // connOpts = tlsNode.addTLSOptions(connOpts);
- // client = tls.connect(connOpts, function() {
- var connOpts = tlsNode.addTLSOptions({host: node.host});
- client = tls.connect(node.port, connOpts, function() {
- // buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
- node.connected = true;
- node.log(RED._("status.connected", {host: node.host, port: node.port}));
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
- });
- }
- else {
- client = net.connect(node.port, node.host, function() {
- node.connected = true;
- node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
- });
- }
- client.setKeepAlive(true,120000);
- client.on('error', function (err) {
- node.log(RED._("tcpin.errors.error",{error:err.toString()}));
- });
- client.on('end', function (err) {
- node.status({});
- node.connected = false;
- });
- client.on('close', function() {
- node.status({fill:"red",shape:"ring",text:"common.status.disconnected"});
- node.connected = false;
- client.destroy();
- if (!node.closing) {
- if (end) {
- end = false;
- reconnectTimeout = setTimeout(setupTcpClient,20);
- }
- else {
- node.log(RED._("tcpin.errors.connection-lost",{host:node.host,port:node.port}));
- reconnectTimeout = setTimeout(setupTcpClient,reconnectTime);
- }
- } else {
- if (node.doneClose) { node.doneClose(); }
- }
- });
- }
- setupTcpClient();
-
- node.on("input", function(msg, nodeSend, nodeDone) {
- if (node.connected && msg.payload != null) {
- if (Buffer.isBuffer(msg.payload)) {
- client.write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- client.write(Buffer.from(msg.payload,'base64'));
- } else {
- client.write(Buffer.from(""+msg.payload));
- }
- if (node.doend === true) {
- end = true;
- if (client) { node.status({}); client.destroy(); }
- }
- }
- nodeDone();
- });
-
- node.on("close", function(done) {
- node.doneClose = done;
- this.closing = true;
- if (client) { client.destroy(); }
- clearTimeout(reconnectTimeout);
- if (!node.connected) { done(); }
- });
-
- }
- else if (node.beserver == "reply") {
- node.on("input",function(msg, nodeSend, nodeDone) {
- if (msg._session && msg._session.type == "tcp") {
- var client = connectionPool[msg._session.id];
- if (client) {
- if (Buffer.isBuffer(msg.payload)) {
- client.write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- client.write(Buffer.from(msg.payload,'base64'));
- } else {
- client.write(Buffer.from(""+msg.payload));
- }
- }
- }
- else {
- for (var i in connectionPool) {
- if (Buffer.isBuffer(msg.payload)) {
- connectionPool[i].write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- connectionPool[i].write(Buffer.from(msg.payload,'base64'));
- } else {
- connectionPool[i].write(Buffer.from(""+msg.payload));
- }
- }
- }
- nodeDone();
- });
- }
- else {
- var connectedSockets = [];
- node.status({text:RED._("tcpin.status.connections",{count:0})});
- let srv = net;
- let connOpts;
- if (n.tls) {
- srv = tls;
- connOpts = tlsNode.addTLSOptions({});
- }
- var server = srv.createServer(connOpts, function (socket) {
- socket.setKeepAlive(true,120000);
- if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
- node.log(RED._("tcpin.status.connection-from",{host:socket.remoteAddress, port:socket.remotePort}));
- socket.on('timeout', function() {
- node.log(RED._("tcpin.errors.timeout",{port:node.port}));
- socket.end();
- });
- socket.on('data', function(d) {
- // console.log("DATA",d)
- });
- socket.on('close',function() {
- node.log(RED._("tcpin.status.connection-closed",{host:socket.remoteAddress, port:socket.remotePort}));
- connectedSockets.splice(connectedSockets.indexOf(socket),1);
- node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})});
- });
- socket.on('error',function() {
- node.log(RED._("tcpin.errors.socket-error",{host:socket.remoteAddress, port:socket.remotePort}));
- connectedSockets.splice(connectedSockets.indexOf(socket),1);
- node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})});
- });
- connectedSockets.push(socket);
- node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})});
- });
-
- node.on("input", function(msg, nodeSend, nodeDone) {
- if (msg.payload != null) {
- var buffer;
- if (Buffer.isBuffer(msg.payload)) {
- buffer = msg.payload;
- } else if (typeof msg.payload === "string" && node.base64) {
- buffer = Buffer.from(msg.payload,'base64');
- } else {
- buffer = Buffer.from(""+msg.payload);
- }
- for (var i = 0; i < connectedSockets.length; i += 1) {
- if (node.doend === true) { connectedSockets[i].end(buffer); }
- else { connectedSockets[i].write(buffer); }
- }
- }
- nodeDone();
- });
-
- server.on('error', function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- }
- });
-
- server.listen(node.port, function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- } else {
- node.log(RED._("tcpin.status.listening-port",{port:node.port}));
- node.on('close', function() {
- for (var c in connectedSockets) {
- if (connectedSockets.hasOwnProperty(c)) {
- connectedSockets[c].end();
- connectedSockets[c].unref();
- }
- }
- server.close();
- node.log(RED._("tcpin.status.stopped-listening",{port:node.port}));
- });
- }
- });
- }
- }
- RED.nodes.registerType("tcp out",TcpOut);
-
-
- function TcpGet(n) {
- RED.nodes.createNode(this,n);
- this.server = n.server;
- this.port = Number(n.port);
- this.out = n.out;
- this.ret = n.ret || "buffer";
- this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
- this.splitc = n.splitc;
- if (n.tls) {
- var tlsNode = RED.nodes.getNode(n.tls);
- }
-
- if (this.out === "immed") { this.splitc = -1; this.out = "time"; }
- if (this.out !== "char") { this.splitc = Number(this.splitc); }
- else {
- if (this.splitc[0] == '\\') {
- this.splitc = parseInt(this.splitc.replace("\\n",0x0A).replace("\\r",0x0D).replace("\\t",0x09).replace("\\e",0x1B).replace("\\f",0x0C).replace("\\0",0x00));
- } // jshint ignore:line
- if (typeof this.splitc == "string") {
- if (this.splitc.substr(0,2) == "0x") {
- this.splitc = parseInt(this.splitc);
- }
- else {
- this.splitc = this.splitc.charCodeAt(0);
- }
- } // jshint ignore:line
- }
-
- var node = this;
-
- var clients = {};
-
- this.on("input", function(msg, nodeSend, nodeDone) {
- var i = 0;
- if ((!Buffer.isBuffer(msg.payload)) && (typeof msg.payload !== "string")) {
- msg.payload = msg.payload.toString();
- }
-
- var host = node.server || msg.host;
- var port = node.port || msg.port;
-
- // Store client information independently
- // the clients object will have:
- // clients[id].client, clients[id].msg, clients[id].timeout
- var connection_id = host + ":" + port;
- if (connection_id !== node.last_id) {
- node.status({});
- node.last_id = connection_id;
- }
- clients[connection_id] = clients[connection_id] || {
- msgQueue: new Denque(),
- connected: false,
- connecting: false
- };
- enqueue(clients[connection_id].msgQueue, {msg:msg, nodeSend:nodeSend, nodeDone:nodeDone});
- clients[connection_id].lastMsg = msg;
-
- if (!clients[connection_id].connecting && !clients[connection_id].connected) {
- var buf;
- if (this.out == "count") {
- if (this.splitc === 0) { buf = Buffer.alloc(1); }
- else { buf = Buffer.alloc(this.splitc); }
- }
- else { buf = Buffer.alloc(65536); } // set it to 64k... hopefully big enough for most TCP packets.... but only hopefully
-
- var connOpts = {host:host, port:port};
- if (n.tls) {
- connOpts = tlsNode.addTLSOptions(connOpts);
- const allowUnauthorized = getAllowUnauthorized();
-
- let options = {
- rejectUnauthorized: !allowUnauthorized,
- ciphers: tls.DEFAULT_CIPHERS,
- checkServerIdentity: tls.checkServerIdentity,
- minDHSize: 1024,
- ...connOpts
- };
-
- if (!options.keepAlive) { options.singleUse = true; }
-
- const context = options.secureContext || tls.createSecureContext(options);
-
- clients[connection_id].client = new tls.TLSSocket(options.socket, {
- allowHalfOpen: options.allowHalfOpen,
- pipe: !!options.path,
- secureContext: context,
- isServer: false,
- requestCert: false, // true,
- rejectUnauthorized: false, // options.rejectUnauthorized !== false,
- session: options.session,
- ALPNProtocols: options.ALPNProtocols,
- requestOCSP: options.requestOCSP,
- enableTrace: options.enableTrace,
- pskCallback: options.pskCallback,
- highWaterMark: options.highWaterMark,
- onread: options.onread,
- signal: options.signal,
- });
- }
- else {
- clients[connection_id].client = net.Socket();
- }
- if (socketTimeout !== null) { clients[connection_id].client.setTimeout(socketTimeout);}
-
- if (host && port) {
- clients[connection_id].connecting = true;
- clients[connection_id].client.connect(connOpts, function() {
- //node.log(RED._("tcpin.errors.client-connected"));
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
- if (clients[connection_id] && clients[connection_id].client) {
- clients[connection_id].connected = true;
- clients[connection_id].connecting = false;
- let event;
- while (event = dequeue(clients[connection_id].msgQueue)) {
- clients[connection_id].client.write(event.msg.payload);
- event.nodeDone();
- }
- if (node.out === "time" && node.splitc < 0) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- clients[connection_id].client.end();
- delete clients[connection_id];
- node.status({});
- }
- }
- });
- }
- else {
- node.warn(RED._("tcpin.errors.no-host"));
- }
- var chunk = "";
- clients[connection_id].client.on('data', function(data) {
- if (node.out === "sit") { // if we are staying connected just send the buffer
- if (clients[connection_id]) {
- const msg = clients[connection_id].lastMsg || {};
- msg.payload = RED.util.cloneMessage(data);
- if (node.ret === "string") {
- try {
- if (node.newline && node.newline !== "" ) {
- chunk += msg.payload.toString();
- let parts = chunk.split(node.newline);
- for (var p=0; p= node.splitc) {
- if (clients[connection_id]) {
- const msg = clients[connection_id].lastMsg || {};
- msg.payload = Buffer.alloc(i);
- buf.copy(msg.payload,0,0,i);
- if (node.ret === "string") {
- try { msg.payload = msg.payload.toString(); }
- catch(e) { node.error("Failed to create string", msg); }
- }
- nodeSend(msg);
- if (clients[connection_id].client) {
- node.status({});
- clients[connection_id].client.destroy();
- delete clients[connection_id];
- }
- i = 0;
- }
- }
- }
- // look for a char
- else {
- buf[i] = data[j];
- i += 1;
- if (data[j] == node.splitc) {
- if (clients[connection_id]) {
- const msg = clients[connection_id].lastMsg || {};
- msg.payload = Buffer.alloc(i);
- buf.copy(msg.payload,0,0,i);
- if (node.ret === "string") {
- try { msg.payload = msg.payload.toString(); }
- catch(e) { node.error("Failed to create string", msg); }
- }
- nodeSend(msg);
- if (clients[connection_id].client) {
- node.status({});
- clients[connection_id].client.destroy();
- delete clients[connection_id];
- }
- i = 0;
- }
- }
- }
- }
- }
- });
-
- clients[connection_id].client.on('end', function() {
- //console.log("END");
- node.status({fill:"grey",shape:"ring",text:"common.status.disconnected"});
- if (clients[connection_id] && clients[connection_id].client) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- clients[connection_id].client = null;
- }
- });
-
- clients[connection_id].client.on('close', function() {
- //console.log("CLOSE");
- if (clients[connection_id]) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- }
-
- var anyConnected = false;
-
- for (var client in clients) {
- if (clients[client].connected) {
- anyConnected = true;
- break;
- }
- }
- if (node.doneClose && !anyConnected) {
- clients = {};
- node.doneClose();
- }
- });
-
- clients[connection_id].client.on('error', function() {
- //console.log("ERROR");
- node.status({fill:"red",shape:"ring",text:"common.status.error"});
- node.error(RED._("tcpin.errors.connect-fail") + " " + connection_id, msg);
- if (clients[connection_id] && clients[connection_id].client) {
- clients[connection_id].client.destroy();
- delete clients[connection_id];
- }
- });
-
- clients[connection_id].client.on('timeout',function() {
- //console.log("TIMEOUT");
- if (clients[connection_id]) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- node.status({fill:"grey",shape:"dot",text:"tcpin.errors.connect-timeout"});
- //node.warn(RED._("tcpin.errors.connect-timeout"));
- if (clients[connection_id].client) {
- clients[connection_id].connecting = true;
-
- var connOpts = {host:host, port:port};
- if (n.tls) {
- connOpts = tlsNode.addTLSOptions(connOpts);
- }
-
- clients[connection_id].client.connect(connOpts, function() {
- clients[connection_id].connected = true;
- clients[connection_id].connecting = false;
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
- });
- }
- }
- });
- }
- else if (!clients[connection_id].connecting && clients[connection_id].connected) {
- if (clients[connection_id] && clients[connection_id].client) {
- let event = dequeue(clients[connection_id].msgQueue)
- clients[connection_id].client.write(event.msg.payload);
- event.nodeDone();
- }
- }
- });
-
- this.on("close", function(done) {
- node.doneClose = done;
- for (var cl in clients) {
- if (clients[cl].hasOwnProperty("client")) {
- clients[cl].client.destroy();
- }
- }
- node.status({});
-
- // this is probably not necessary and may be removed
- var anyConnected = false;
- for (var c in clients) {
- if (clients[c].connected) {
- anyConnected = true;
- break;
- }
- }
- if (!anyConnected) { clients = {}; }
- done();
- });
-
- }
- RED.nodes.registerType("tcp request",TcpGet);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.js b/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.js
deleted file mode 100644
index e16c4ec23..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.js
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- const Ajv = require('ajv');
- const ajv = new Ajv({allErrors: true});
- ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'));
-
- function JSONNode(n) {
- RED.nodes.createNode(this,n);
- this.indent = n.pretty ? 4 : 0;
- this.action = n.action||"";
- this.property = n.property||"payload";
- this.schema = null;
- this.compiledSchema = null;
-
- var node = this;
-
- this.on("input", function(msg,send,done) {
- var validate = false;
- if (msg.schema) {
- // If input schema is different, re-compile it
- if (JSON.stringify(this.schema) != JSON.stringify(msg.schema)) {
- try {
- this.compiledSchema = ajv.compile(msg.schema);
- this.schema = msg.schema;
- } catch(e) {
- this.schema = null;
- this.compiledSchema = null;
- done(RED._("json.errors.schema-error-compile"));
- return;
- }
- }
- validate = true;
- }
- 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") {
- // node.warn(RED._("json.errors.dropped")); done();
- // }
- // else
- if (node.action === "" || node.action === "obj") {
- try {
- RED.util.setMessageProperty(msg,node.property,JSON.parse(value));
- if (validate) {
- if (this.compiledSchema(msg[node.property])) {
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- send(msg);
- done();
- }
- }
- catch(e) { done(e.message); }
- } else {
- // If node.action is str and value is str
- if (validate) {
- if (this.compiledSchema(JSON.parse(msg[node.property]))) {
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- send(msg);
- done();
- }
- }
- }
- else if ((typeof value === "object") || (typeof value === "boolean") || (typeof value === "number")) {
- if (node.action === "" || node.action === "str") {
- if (!Buffer.isBuffer(value)) {
- try {
- if (validate) {
- if (this.compiledSchema(value)) {
- RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
- send(msg);
- done();
- }
- }
- catch(e) { done(RED._("json.errors.dropped-error")); }
- }
- else { node.warn(RED._("json.errors.dropped-object")); done(); }
- } else {
- // If node.action is obj and value is object
- if (validate) {
- if (this.compiledSchema(value)) {
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- send(msg);
- done();
- }
- }
- }
- else { node.warn(RED._("json.errors.dropped")); done(); }
- }
- else { send(msg); done(); } // If no property - just pass it on.
- });
- }
- RED.nodes.registerType("json",JSONNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/icons/guide.svg b/packages/node_modules/@node-red/nodes/icons/guide.svg
new file mode 100644
index 000000000..b46237cfb
--- /dev/null
+++ b/packages/node_modules/@node-red/nodes/icons/guide.svg
@@ -0,0 +1 @@
+
\ No newline at end of file