mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #3867 from Steve-Mcl/improve-nodesdir-scan
Fix nodesDir scan when node package has js/html in sub dir to package.json
This commit is contained in:
commit
02af01d2ca
@ -43,37 +43,40 @@ function load(disableNodePathScan) {
|
|||||||
return loadModuleFiles(modules);
|
return loadModuleFiles(modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function splitPath(p) {
|
||||||
|
return path.posix.normalize((p || '').replace(/\\/g, path.sep)).split(path.sep)
|
||||||
|
}
|
||||||
|
|
||||||
function loadModuleTypeFiles(module, type) {
|
function loadModuleTypeFiles(module, type) {
|
||||||
const things = module[type];
|
const things = module[type];
|
||||||
var first = true;
|
let first = true;
|
||||||
var promises = [];
|
const promises = [];
|
||||||
for (var thingName in things) {
|
for (let thingName in things) {
|
||||||
/* istanbul ignore else */
|
/* istanbul ignore else */
|
||||||
if (things.hasOwnProperty(thingName)) {
|
if (things.hasOwnProperty(thingName)) {
|
||||||
if (module.name != "node-red" && first) {
|
if (module.name != "node-red" && first) {
|
||||||
// Check the module directory exists
|
// Check the module directory exists
|
||||||
first = false;
|
first = false;
|
||||||
var fn = things[thingName].file;
|
let moduleFn = module.path
|
||||||
var parts = fn.split("/");
|
const fn = things[thingName].file
|
||||||
var i = parts.length-1;
|
const parts = splitPath(fn)
|
||||||
for (;i>=0;i--) {
|
const nmi = parts.indexOf('node_modules')
|
||||||
if (parts[i] == "node_modules") {
|
if(nmi > -1) {
|
||||||
break;
|
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 {
|
try {
|
||||||
var stat = fs.statSync(moduleFn);
|
const stat = fs.statSync(moduleFn);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
// Module not found, don't attempt to load its nodes
|
break; // Module not found, don't attempt to load its nodes
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var promise;
|
let promise;
|
||||||
if (type === "nodes") {
|
if (type === "nodes") {
|
||||||
promise = loadNodeConfig(things[thingName]);
|
promise = loadNodeConfig(things[thingName]);
|
||||||
} else if (type === "plugins") {
|
} else if (type === "plugins") {
|
||||||
@ -82,8 +85,7 @@ function loadModuleTypeFiles(module, type) {
|
|||||||
promises.push(
|
promises.push(
|
||||||
promise.then(
|
promise.then(
|
||||||
(function() {
|
(function() {
|
||||||
var m = module.name;
|
const n = thingName;
|
||||||
var n = thingName;
|
|
||||||
return function(nodeSet) {
|
return function(nodeSet) {
|
||||||
things[n] = nodeSet;
|
things[n] = nodeSet;
|
||||||
return nodeSet;
|
return nodeSet;
|
||||||
@ -93,7 +95,6 @@ function loadModuleTypeFiles(module, type) {
|
|||||||
);
|
);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
//
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,6 +156,16 @@ function scanDirForNodesModules(dir,moduleName,package) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we have found a package.json, this IS a node_module, lets see if it is a node-red node
|
||||||
|
if (!isNodeRedModule && files.indexOf('package.json') > -1) {
|
||||||
|
package = getPackageDetails(dir) // get package details
|
||||||
|
if(package && package.isNodeRedModule) {
|
||||||
|
isNodeRedModule = true
|
||||||
|
files = ['package.json'] // shortcut the file scan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let i=0;i<files.length;i++) {
|
for (let i=0;i<files.length;i++) {
|
||||||
let fn = files[i];
|
let fn = files[i];
|
||||||
if (!isNodeRedModule && /^@/.test(fn)) {
|
if (!isNodeRedModule && /^@/.test(fn)) {
|
||||||
|
@ -185,10 +185,17 @@ function loadNodeConfigs() {
|
|||||||
function addModule(module) {
|
function addModule(module) {
|
||||||
moduleNodes[module.name] = [];
|
moduleNodes[module.name] = [];
|
||||||
moduleConfigs[module.name] = module;
|
moduleConfigs[module.name] = module;
|
||||||
// console.log("registry.js.addModule",module.name,"user?",module.user,"usedBy",module.usedBy,"dependencies",module.dependencies)
|
for (const setName in module.nodes) {
|
||||||
for (var setName in module.nodes) {
|
|
||||||
if (module.nodes.hasOwnProperty(setName)) {
|
if (module.nodes.hasOwnProperty(setName)) {
|
||||||
var set = module.nodes[setName];
|
const set = module.nodes[setName];
|
||||||
|
if (!set.types) {
|
||||||
|
const err = new Error("Set has no types")
|
||||||
|
err.code = "set_has_no_types"
|
||||||
|
err.details = {
|
||||||
|
...set
|
||||||
|
}
|
||||||
|
set.err = err
|
||||||
|
}
|
||||||
moduleNodes[module.name].push(set.name);
|
moduleNodes[module.name].push(set.name);
|
||||||
nodeList.push(set.id);
|
nodeList.push(set.id);
|
||||||
if (!set.err) {
|
if (!set.err) {
|
||||||
|
@ -161,6 +161,8 @@ function start() {
|
|||||||
for (i=0;i<nodeErrors.length;i+=1) {
|
for (i=0;i<nodeErrors.length;i+=1) {
|
||||||
if (nodeErrors[i].err.code === "type_already_registered") {
|
if (nodeErrors[i].err.code === "type_already_registered") {
|
||||||
log.warn("["+nodeErrors[i].id+"] "+log._("server.type-already-registered",{type:nodeErrors[i].err.details.type,module: nodeErrors[i].err.details.moduleA}));
|
log.warn("["+nodeErrors[i].id+"] "+log._("server.type-already-registered",{type:nodeErrors[i].err.details.type,module: nodeErrors[i].err.details.moduleA}));
|
||||||
|
} else if (nodeErrors[i].err.code === "set_has_no_types") {
|
||||||
|
log.warn("["+nodeErrors[i].id+"] "+log._("server.set-has-no-types", nodeErrors[i].err.details));
|
||||||
} else {
|
} else {
|
||||||
log.warn("["+nodeErrors[i].id+"] "+nodeErrors[i].err);
|
log.warn("["+nodeErrors[i].id+"] "+nodeErrors[i].err);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"errors-help": "Run with -v for details",
|
"errors-help": "Run with -v for details",
|
||||||
"missing-modules": "Missing node modules:",
|
"missing-modules": "Missing node modules:",
|
||||||
"node-version-mismatch": "Node module cannot be loaded on this version. Requires: __version__ ",
|
"node-version-mismatch": "Node module cannot be loaded on this version. Requires: __version__ ",
|
||||||
|
"set-has-no-types": "Set does not have any types. name: '__name__', module: '__module__', file: '__file__'",
|
||||||
"type-already-registered": "'__type__' already registered by module __module__",
|
"type-already-registered": "'__type__' already registered by module __module__",
|
||||||
"removing-modules": "Removing modules from config",
|
"removing-modules": "Removing modules from config",
|
||||||
"added-types": "Added node types:",
|
"added-types": "Added node types:",
|
||||||
|
@ -329,17 +329,36 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
localfilesystem.init({nodesDir:[nodesDir2]});
|
localfilesystem.init({nodesDir:[nodesDir2]});
|
||||||
const nodeModule = localfilesystem.getModuleFiles();
|
const nodeModule = localfilesystem.getModuleFiles();
|
||||||
const loaded = Object.keys(nodeModule)
|
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('@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('testnode2').should.greaterThan(-1, "Should load testnode2")
|
||||||
loaded.indexOf('test-theme2').should.greaterThan(-1, "Should load test-theme2")
|
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('name','@test/testnode');
|
||||||
nodeModule['@test/testnode'].should.have.a.property('version','1.0.0');
|
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('nodes');
|
||||||
nodeModule['@test/testnode'].should.have.a.property('path');
|
nodeModule['@test/testnode'].should.have.a.property('path');
|
||||||
nodeModule['@test/testnode'].should.have.a.property('user', false);
|
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('name','testnode2');
|
||||||
nodeModule['testnode2'].should.have.a.property('version','1.0.0');
|
nodeModule['testnode2'].should.have.a.property('version','1.0.0');
|
||||||
nodeModule['testnode2'].should.have.a.property('nodes');
|
nodeModule['testnode2'].should.have.a.property('nodes');
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('lower-case2',{
|
||||||
|
category: 'function',
|
||||||
|
color: '#a6bbcf',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:1,
|
||||||
|
icon: "file.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"lower-case2";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="lower-case2">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="lower-case2">
|
||||||
|
<p>A simple node that converts the message payloads into all lower-case2 characters</p>
|
||||||
|
</script>
|
@ -0,0 +1,11 @@
|
|||||||
|
module.exports = function(RED) {
|
||||||
|
function LowerCaseNode(config) {
|
||||||
|
RED.nodes.createNode(this,config);
|
||||||
|
var node = this;
|
||||||
|
node.on('input', function(msg) {
|
||||||
|
msg.payload = msg.payload.toLowerCase();
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("lower-case2",LowerCaseNode);
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name" : "@lowercase/lower-case2",
|
||||||
|
"node-red" : {
|
||||||
|
"nodes": {
|
||||||
|
"lower-case": "lower-case2/lower-case.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "2.0.0"
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('lower-case',{
|
||||||
|
category: 'function',
|
||||||
|
color: '#a6bbcf',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:1,
|
||||||
|
icon: "file.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"lower-case";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="lower-case">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="lower-case">
|
||||||
|
<p>A simple node that converts the message payloads into all lower-case characters</p>
|
||||||
|
</script>
|
@ -0,0 +1,11 @@
|
|||||||
|
module.exports = function(RED) {
|
||||||
|
function LowerCaseNode(config) {
|
||||||
|
RED.nodes.createNode(this,config);
|
||||||
|
var node = this;
|
||||||
|
node.on('input', function(msg) {
|
||||||
|
msg.payload = msg.payload.toLowerCase();
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("lower-case",LowerCaseNode);
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name" : "lower-case",
|
||||||
|
"node-red" : {
|
||||||
|
"nodes": {
|
||||||
|
"lower-case": "lower-case/lower-case.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user