From d6bb3a558f6da935e05488cb1708562b0b242ebb Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Sat, 3 Sep 2022 21:23:38 +0100 Subject: [PATCH 1/4] fix loading node package in nodesDir on linux fixes #3861 --- .../@node-red/registry/lib/loader.js | 39 ++++++++++--------- .../@node-red/registry/lib/localfilesystem.js | 10 +++++ .../@node-red/registry/lib/registry.js | 11 +++++- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/packages/node_modules/@node-red/registry/lib/loader.js b/packages/node_modules/@node-red/registry/lib/loader.js index 61f28ab86..3f0487750 100644 --- a/packages/node_modules/@node-red/registry/lib/loader.js +++ b/packages/node_modules/@node-red/registry/lib/loader.js @@ -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) - // } } } diff --git a/packages/node_modules/@node-red/registry/lib/localfilesystem.js b/packages/node_modules/@node-red/registry/lib/localfilesystem.js index da4006ecc..edb805572 100644 --- a/packages/node_modules/@node-red/registry/lib/localfilesystem.js +++ b/packages/node_modules/@node-red/registry/lib/localfilesystem.js @@ -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 Date: Sat, 3 Sep 2022 21:37:27 +0100 Subject: [PATCH 2/4] add test for specific arrangement of node package --- .../registry/lib/localfilesystem_spec.js | 21 ++++++++++++++- .../@lower-case2/lower-case2/lower-case.html | 26 +++++++++++++++++++ .../@lower-case2/lower-case2/lower-case.js | 11 ++++++++ .../nodesDir2/@lower-case2/package.json | 9 +++++++ .../lower-case/lower-case/lower-case.html | 26 +++++++++++++++++++ .../lower-case/lower-case/lower-case.js | 11 ++++++++ .../nodesDir2/lower-case/package.json | 9 +++++++ 7 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/package.json create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.html create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.js create mode 100644 test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/package.json diff --git a/test/unit/@node-red/registry/lib/localfilesystem_spec.js b/test/unit/@node-red/registry/lib/localfilesystem_spec.js index 3b1bb63f3..3ce74c158 100644 --- a/test/unit/@node-red/registry/lib/localfilesystem_spec.js +++ b/test/unit/@node-red/registry/lib/localfilesystem_spec.js @@ -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'); diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.html new file mode 100644 index 000000000..617f48491 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.html @@ -0,0 +1,26 @@ + + + + + \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.js new file mode 100644 index 000000000..73579ba04 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/lower-case2/lower-case.js @@ -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); +} \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/package.json new file mode 100644 index 000000000..6b6ce9aa9 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@lower-case2/package.json @@ -0,0 +1,9 @@ +{ + "name" : "@lowercase/lower-case2", + "node-red" : { + "nodes": { + "lower-case": "lower-case2/lower-case.js" + } + }, + "version": "2.0.0" +} \ No newline at end of file diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.html new file mode 100644 index 000000000..e57d51131 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.html @@ -0,0 +1,26 @@ + + + + + diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.js new file mode 100644 index 000000000..006b35eb6 --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/lower-case/lower-case.js @@ -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); +} diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/package.json new file mode 100644 index 000000000..a632eaddd --- /dev/null +++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/lower-case/package.json @@ -0,0 +1,9 @@ +{ + "name" : "lower-case", + "node-red" : { + "nodes": { + "lower-case": "lower-case/lower-case.js" + } + }, + "version": "1.0.0" +} From e6b379358aa1278d261bc7bee2a1be09f9fc41f0 Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Thu, 29 Sep 2022 21:28:13 +0100 Subject: [PATCH 3/4] better logging of set with no types --- .../@node-red/registry/lib/registry.js | 15 ++++++++------- .../node_modules/@node-red/runtime/lib/index.js | 2 ++ .../@node-red/runtime/locales/en-US/runtime.json | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/node_modules/@node-red/registry/lib/registry.js b/packages/node_modules/@node-red/registry/lib/registry.js index 6e3ed6d5b..b0ca22717 100644 --- a/packages/node_modules/@node-red/registry/lib/registry.js +++ b/packages/node_modules/@node-red/registry/lib/registry.js @@ -185,17 +185,18 @@ function loadNodeConfigs() { function addModule(module) { moduleNodes[module.name] = []; moduleConfigs[module.name] = module; - 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(setName === 'lower-case') { + delete set.types + } if (!set.types) { - const err = new Error("Node has no types") - err.code = "has_no_types" + const err = new Error("Set has no types") + err.code = "set_has_no_types" err.details = { - setName: set.name, - set: { ...set } + ...set } - console.warn(err) set.err = err } moduleNodes[module.name].push(set.name); diff --git a/packages/node_modules/@node-red/runtime/lib/index.js b/packages/node_modules/@node-red/runtime/lib/index.js index 88b3b8293..a886cd2ca 100644 --- a/packages/node_modules/@node-red/runtime/lib/index.js +++ b/packages/node_modules/@node-red/runtime/lib/index.js @@ -161,6 +161,8 @@ function start() { for (i=0;i Date: Tue, 4 Oct 2022 13:36:23 +0100 Subject: [PATCH 4/4] remove debug/test code --- packages/node_modules/@node-red/registry/lib/registry.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/node_modules/@node-red/registry/lib/registry.js b/packages/node_modules/@node-red/registry/lib/registry.js index b0ca22717..389285dbc 100644 --- a/packages/node_modules/@node-red/registry/lib/registry.js +++ b/packages/node_modules/@node-red/registry/lib/registry.js @@ -188,9 +188,6 @@ function addModule(module) { for (const setName in module.nodes) { if (module.nodes.hasOwnProperty(setName)) { const set = module.nodes[setName]; - if(setName === 'lower-case') { - delete set.types - } if (!set.types) { const err = new Error("Set has no types") err.code = "set_has_no_types"