Scenario:
NodeRED sits on a double network, can reach a backend and can be reached by the browser. The browser can't reach the backend directly.
A configuration node has two entries:
baseURI (the URI the backend can be reached - not necessarily http(s)
category: currently String
FIlling in the values and letting the node do its thing works like a charm. Now the challenge: each backend supports different categories and the "category" input should be replaced with a dropdown list showing the available categories. The backend has such a function.
The basic mechanic using a typeInput and reaching into the backend works:
// Edit snipped
oneditprepare: function () {
let apiList = getApiList(RED, $('#node-config-input-baseUrl').val());
$('#node-config-input-api').typedInput(apiList);
}
// calling backend
const getApiList = (RED, hostname) => {
console.log(`Retrieve API List for ${hostname}`);
let options = RED.settings.dominoConnectorApiList;
return {
types: [
{
value: 'apis',
options: options
}
]
};
};
On the NodeRED side:
const apiList = (baseURI) => {
// HOW can I run this at setup time with the baseURI
console.log('Running API List');
// Hardcoded for now
return [
{ value: 'basis', label: 'Basic CRUD' },
{ value: 'admin', label: 'Domino admin' },
{ value: 'pim', label: 'email, tasks, calendar (PIM)' },
{ value: 'poi', label: 'Office functions' },
{ value: 'setup', label: 'Setup REST' }
];
};
module.exports = function (RED) {
function DominoConnectorNode(config) {
RED.nodes.createNode(this, config);
const node = this;
node.baseUrl = config.baseUrl;
node.api = config.api;
}
RED.nodes.registerType('domino-connector', DominoConnectorNode, {
settings: {
dominoConnectorApiList: {
value: apiList(),
exportable: true
}
}
});
};
There is another option. But only for something that does not change until Node-RED (re)loads. The register function in the runtime allows passing of some data which can be read in the Editor.
As in this example:
/** 2) Register the node by name. This must be called before overriding any of the
* Node functions. */
RED.nodes.registerType(uib.moduleName, nodeInstance, {
credentials: {
jwtSecret: { type: 'password' },
},
// Makes these available to the editor as RED.settings.uibuilderxxxxxx
settings: {
// The server's NODE_ENV environment var (e.g. PRODUCTION or DEVELOPMENT)
uibuilderNodeEnv: { value: process.env.NODE_ENV, exportable: true },
// Available templates and details
uibuilderTemplates: { value: templateConf, exportable: true },
// Custom server details
uibuilderCustomServer: { value: (uib.customServer), exportable: true },
// Current version of uibuilder
uibuilderCurrentVersion: { value: (uib.version), exportable: true },
// Should the editor tell the user that a redeploy is needed (based on uib versions)
uibuilderRedeployNeeded: { value: uib.reDeployNeeded, exportable: true },
// List of the deployed uib instances [{node_id: url}]
uibuilderInstances: { value: uib.instances, exportable: true },
// uibRoot
uibuilderRootFolder: { value: uib.rootFolder, exportable: true },
},
})
The properties passed back have to start with the name of the node I believe.
In the example, the uibuilderInstances property is only correct at the time that Node-RED starts since it will change if someone, for example adds or removes a uibuilder node. So it is really a bit superfluous since I have to have an API anyway. I'll remove it one day. But the uibuilderCurrentVersion cannot change when node-red is running.
How very true. And this has prompted me to improve some Editor related code where I turn on debug console output. Used to be if the node-red editor was accessed on localhost, it is now if the NODE_ENV variable on the server was set to "dev" or "development".
A little off-topic, but I apply the same approach in .NET, but with clr "preprocessor directives".
One of my projects in github (.NET), used to try and connect to a server on the host, if a debugger was attached - but had reports that when they use the lib while developing their app - it would timeout.
So, I added a 3rd profile Debug - Local Server that adds preprocessor directives, that is checked before trying to connect to a local server.
#if DEBUG_LOCAL
// connect to local sever
#endif
meaning they can still debug without connecting to a local server, by using the default Debug profile