Skip to content

Commit 34089ae

Browse files
Kazuki-Nakanishiknolleary
authored andcommitted
Allow a node to declare what settings should be made available to the editor. (node-red#1185)
* Implement register/exportNodeSettings. * Change normaliseRegisterTypeName to normaliseNodeTypeName. Force it to name in a camel case.
1 parent fca77a8 commit 34089ae

6 files changed

Lines changed: 156 additions & 23 deletions

File tree

nodes/core/io/21-httprequest.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,6 @@ module.exports = function(RED) {
216216
credentials: {
217217
user: {type:"text"},
218218
password: {type: "password"}
219-
},
220-
settings: {
221-
httpRequestColour: {
222-
value: "red",
223-
// validate: function(v) { return IT MUST BE A NUMBER },
224-
// required: false,
225-
exportable: true
226-
}
227219
}
228220
});
229221
}

red/runtime/nodes/registry/registry.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ function enableNodeSet(typeOrId) {
493493
delete config.err;
494494
config.enabled = true;
495495
nodeConfigCache = null;
496+
settings.enableNodeSettings(config.types);
496497
return saveNodeList().then(function() {
497498
return filterNodeInfo(config);
498499
});
@@ -515,6 +516,7 @@ function disableNodeSet(typeOrId) {
515516
// TODO: persist setting
516517
config.enabled = false;
517518
nodeConfigCache = null;
519+
settings.disableNodeSettings(config.types);
518520
return saveNodeList().then(function() {
519521
return filterNodeInfo(config);
520522
});

red/runtime/settings.js

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ var when = require("when");
1818
var clone = require("clone");
1919
var assert = require("assert");
2020
var log = require("./log");
21+
var util = require("./util");
2122

2223
var userSettings = null;
2324
var globalSettings = null;
2425
var nodeSettings = null;
26+
var disableNodeSettings = null;
2527
var storage = null;
2628

2729
var persistentSettings = {
@@ -40,6 +42,7 @@ var persistentSettings = {
4042
}
4143
globalSettings = null;
4244
nodeSettings = {};
45+
disableNodeSettings = {};
4346
},
4447
load: function(_storage) {
4548
storage = _storage;
@@ -103,24 +106,49 @@ var persistentSettings = {
103106
storage = null;
104107
},
105108
registerNodeSettings: function(type, opts) {
106-
//console.log(type,opts);
107-
// 1. TODO: validate the option names are allowed for the node type
108-
109-
// 2. store this information against the node type
110-
nodeSettings[type] = opts;
111-
112-
113-
// TODO: remove the node settings if the node is disabled/removed from runtime
109+
try {
110+
for (var property in opts) {
111+
if (opts.hasOwnProperty(property)) {
112+
var normalisedType = util.normaliseNodeTypeName(type);
113+
if (!property.startsWith(normalisedType)) {
114+
throw new Error("The name of node setting property " + property + " must start with \"" + normalisedType + "\" (case sensitive).");
115+
}
116+
}
117+
}
118+
nodeSettings[type] = opts;
119+
} catch (err) {
120+
console.log(err.toString());
121+
}
114122
},
115123
exportNodeSettings: function(safeSettings) {
116-
// 1. forEach type in nodeSettings...
117-
// 2. forEach setting for that type...
118-
// 3. if globalSettings has a property with the required name...
119-
// 4. set safeSettings.property to that value
120-
// 5. else if the setting has a default 'value' provided
121-
// 6. set safeSettings.property to that value
124+
safeSettings["nodeSettings"] = {};
125+
for (var type in nodeSettings) {
126+
if (nodeSettings.hasOwnProperty(type) && !disableNodeSettings[type]) {
127+
var nodeTypeSettings = nodeSettings[type];
128+
for (var property in nodeTypeSettings) {
129+
if (nodeTypeSettings.hasOwnProperty(property)) {
130+
var setting = nodeTypeSettings[property];
131+
if (userSettings.hasOwnProperty(property)) {
132+
safeSettings["nodeSettings"][property] = userSettings[property];
133+
} else if (setting.exportable) {
134+
safeSettings["nodeSettings"][property] = setting.value;
135+
}
136+
}
137+
}
138+
}
139+
}
122140

123141
return safeSettings;
142+
},
143+
enableNodeSettings: function(types) {
144+
types.forEach(function(type) {
145+
disableNodeSettings[type] = false;
146+
});
147+
},
148+
disableNodeSettings: function(types) {
149+
types.forEach(function(type) {
150+
disableNodeSettings[type] = true;
151+
});
124152
}
125153
}
126154

red/runtime/util.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ function evaluateNodeProperty(value, type, node, msg) {
328328
return value;
329329
}
330330

331+
function normaliseNodeTypeName(name) {
332+
var result = name.replace(/[^a-zA-Z0-9]/g, " ");
333+
result = result.trim();
334+
result = result.replace(/ +/g, " ");
335+
result = result.replace(/ ./g,
336+
function(s) {
337+
return s.charAt(1).toUpperCase();
338+
}
339+
);
340+
result = result.charAt(0).toLowerCase() + result.slice(1);
341+
return result;
342+
}
331343

332344
module.exports = {
333345
ensureString: ensureString,
@@ -338,5 +350,6 @@ module.exports = {
338350
getMessageProperty: getMessageProperty,
339351
setMessageProperty: setMessageProperty,
340352
evaluateNodeProperty: evaluateNodeProperty,
341-
normalisePropertyExpression: normalisePropertyExpression
353+
normalisePropertyExpression: normalisePropertyExpression,
354+
normaliseNodeTypeName: normaliseNodeTypeName
342355
};

test/red/runtime/settings_spec.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,85 @@ describe("red/settings", function() {
142142
settings.should.not.have.property("c");
143143

144144
});
145+
146+
it('registers node settings and exports them', function() {
147+
var userSettings = {};
148+
settings.init(userSettings);
149+
settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}, injectSize:{value:"100", exportable:true}} );
150+
settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:false}, mqttSize:{value:"50", exportable:true}} );
151+
settings.registerNodeSettings("http request", {httpRequest1:{value:"a1", exportable:true}} );
152+
settings.registerNodeSettings(" http--request<> ", {httpRequest2:{value:"a2", exportable:true}} );
153+
settings.registerNodeSettings("_http_request_", {httpRequest3:{value:"a3", exportable:true}} );
154+
settings.registerNodeSettings("mQtT", {mQtTColor:{value:"purple", exportable:true}} );
155+
settings.registerNodeSettings("abc123", {abc123:{value:"def456", exportable:true}} );
156+
var safeSettings = {};
157+
settings.exportNodeSettings(safeSettings);
158+
safeSettings["nodeSettings"].should.have.property("injectColor", "red");
159+
safeSettings["nodeSettings"].should.have.property("injectSize", "100");
160+
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
161+
safeSettings["nodeSettings"].should.have.property("mqttSize", "50");
162+
safeSettings["nodeSettings"].should.have.property("httpRequest1", "a1");
163+
safeSettings["nodeSettings"].should.have.property("httpRequest2", "a2");
164+
safeSettings["nodeSettings"].should.have.property("httpRequest3", "a3");
165+
safeSettings["nodeSettings"].should.have.property("mQtTColor", "purple");
166+
safeSettings["nodeSettings"].should.have.property("abc123", "def456");
167+
});
168+
169+
it('prohibits registering the property whose name do not start with type name', function() {
170+
var userSettings = {};
171+
settings.init(userSettings);
172+
settings.registerNodeSettings("inject", {color:{value:"red", exportable:true}} );
173+
settings.registerNodeSettings("_a_b_1_", {ab1Color:{value:"red", exportable:true}} );
174+
settings.registerNodeSettings("AB2", {AB2Color:{value:"red", exportable:true}} );
175+
settings.registerNodeSettings("abcDef", {abcColor:{value:"red", exportable:true}} );
176+
var safeSettings = {};
177+
settings.exportNodeSettings(safeSettings);
178+
safeSettings["nodeSettings"].should.not.have.property("color");
179+
safeSettings["nodeSettings"].should.not.have.property("ab1Color", "blue");
180+
safeSettings["nodeSettings"].should.not.have.property("AB2Color");
181+
safeSettings["nodeSettings"].should.not.have.property("abcColor");
182+
});
183+
184+
it('overwrites node settings with user settings', function() {
185+
var userSettings = {
186+
injectColor: "green",
187+
mqttColor: "yellow",
188+
c: [1,2,3]
189+
}
190+
settings.init(userSettings);
191+
settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
192+
var safeSettings = {};
193+
settings.exportNodeSettings(safeSettings);
194+
safeSettings["nodeSettings"].should.have.property("injectColor", "green");
195+
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
196+
});
197+
198+
it('disables/enables node settings', function() {
199+
var userSettings = {};
200+
settings.init(userSettings);
201+
202+
var safeSettings = {};
203+
settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
204+
settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:true}} );
205+
settings.registerNodeSettings("http request", {httpRequestColor:{value:"yellow", exportable:true}} );
206+
settings.exportNodeSettings(safeSettings);
207+
safeSettings["nodeSettings"].should.have.property("injectColor", "red");
208+
safeSettings["nodeSettings"].should.have.property("mqttColor", "purple");
209+
safeSettings["nodeSettings"].should.have.property("httpRequestColor", "yellow");
210+
211+
var types = ["inject", "mqtt"];
212+
settings.disableNodeSettings(types);
213+
settings.exportNodeSettings(safeSettings);
214+
safeSettings["nodeSettings"].should.not.have.property("injectColor");
215+
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
216+
safeSettings["nodeSettings"].should.have.property("httpRequestColor", "yellow");
217+
218+
types = ["inject"];
219+
settings.enableNodeSettings(types);
220+
settings.exportNodeSettings(safeSettings);
221+
safeSettings["nodeSettings"].should.have.property("injectColor", "red");
222+
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
223+
safeSettings["nodeSettings"].should.have.property("httpRequestColor", "yellow");
224+
});
225+
145226
});

test/red/runtime/util_spec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,21 @@ describe("red/util", function() {
364364
it("fail <blank>",function() { testInvalid("");})
365365

366366
});
367+
368+
describe('normaliseNodeTypeName', function() {
369+
function normalise(input, expected) {
370+
var result = util.normaliseNodeTypeName(input);
371+
result.should.eql(expected);
372+
}
373+
374+
it('pass blank',function() { normalise("", "") });
375+
it('pass ab1',function() { normalise("ab1", "ab1") });
376+
it('pass AB1',function() { normalise("AB1", "aB1") });
377+
it('pass a b 1',function() { normalise("a b 1", "aB1") });
378+
it('pass a-b-1',function() { normalise("a-b-1", "aB1") });
379+
it('pass ab1 ',function() { normalise(" ab1 ", "ab1") });
380+
it('pass _a_b_1_',function() { normalise("_a_b_1_", "aB1") });
381+
it('pass http request',function() { normalise("http request", "httpRequest") });
382+
it('pass HttpRequest',function() { normalise("HttpRequest", "httpRequest") });
383+
});
367384
});

0 commit comments

Comments
 (0)