Javascript library

I know there are multiple backdoors into node red for creating reusable functionality. But I'd like a first-class javascript library instead. It would be much easier to view and edit a shared js code inside node red, than having to go backend and restart on each change. I'd like something similar to a subflow, but not as independant instances with separate context (or even context at all). I also don't like the function library for obvious reasons.

Any plans or possibilities for this?

If I had read this right.

Isn’t this what link call node is all about?

It allows “reusable” decision making?
And can include any combination of nodes.

This link call node works as a singleton, and doesn’t spawn “instances”

1 Like

Problems with link node is it only has 1 output, so if you handle error/success as 2 separate outputs, you need to add that outside at the caller side each time you use it. This alone makes me prefer subflows at the cost of independent instances. Further it seems to require timeout for some reason, even when not relevant? Can be mitigated by setting a high value, but still seems like a workaround. You'd also need to allocate space in a flow somewhere for your library. Possibly making a separate "utils" flow with all your link call sources.

I'd much rather just have a js library with exported functions. Something I can do via backdoor, but would much rather have it inside NR. Unrelated to Node Red, but Thingsboard (IoT platform) has this javascript library page exactly for this reason.

A singelton subflow would probably be a good alternative also. A subflow has far better interface flexibility than a simple link call. Or a "singleton" function node would still be preferable over link call IMO. Perhaps not even a singleton, as many use cases wouldn't even require context to be stored between messages.

I have so many usecases outside the simple "send a message and get a message in return". For example I have a subflow with no input, only outputs a message at selected intervals (1-min / 5- min / hourly etc.) with flags in the msg to indicate wheter it is 5-min interval, 1-min interval and/or hourly (minute 0). This is useful when you need to fetch different data at different times. No need to have independent instances, as it is essentially stateless (except for the env options set in the calling node).

But it could be as simple as a function to format dates or whatever. Something I'd use all the time, but wouldn't need a separate instance or even a node. Could just be pure js function. Could put this into the library, but you can only copy the code from it? Not use it directly. So whenever you need to change it, you're in a world of hurt.

Perhaps the closest thing to what I need would be to add functions to global context. Still feels hacky and 2nd grade solution, particularly with reference by string.

I think that the main issue is that this isn't really how Node.js works. But also, allowing external dynamic JavaScript (which I think is what you are asking for?), would potentially be a security weakness.

There are, of course, now several mechanisms to support this. You mention globals and you can certainly reference an external module in setttings.js which load functions into the global context.

You can also create a runtime and/or an editor plugin which can add extra features.

And, of course, you can create your own Nodes.

But all of these require Node-RED to be restarted in order to pick up changes because that's how node.js generally works.

It isn't impossible to have something that could pick up dynamic changes but it isn't really simple and could open Node-RED to other issues if not treated carefully. And we remember that even changes to flows cause at least part of Node-RED to restart on each deployment.

For what you want, I would think that your current best option would be a local custom node module, possibly with a background watch function to restart node-red as needed.


There is though, a more radical option. Just because you have the hammer of Node-RED does not mean that every compute job is a nail! :smiley:

You could easily create another node.js (or Python, Go, Rust, ...) microservice with an API (websockets, mqtt, http, tcp, udp, UNIX Pipes, ....) that contains your custom functions and you interface with that from your Flows. Best of all worlds.

This the approach I'm using to simplify some of my old flows.
e.g. for a specific date formatting, it can easily be called from a function node with

lastActivated = global.get("formatDate")(timestamp)

If you store these on first flow tab, they get initialised first, and there's only one place to edit them.

// Store formatted time Function

global.set("formatDate", (function () {
    const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

    return function (timestamp) {
        const now = new Date(timestamp);
        const pad = n => n.toString().padStart(2, '0');
        const day = days[now.getDay()];
        const month = months[now.getMonth()];
        return `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())} ${day} ${now.getDate()} ${month}`;
    };
})());
2 Likes

Perhaps there is some intricate detail I'm missing, but how is this not already the case? You can make a function node on the fly and apply any code there you want to execute. All working in node.js. You can even make your own library on and access it from global context as shown by smcgann99. If that is already possible, I would think it is possible to do the same but have a dedicated space for it, instead of DIY hacky solutions.

Function nodes execute inside a VM for this very reason. It is also the reason you are able to turn off the ability to add extra modules for function nodes from within Node-RED. Uncontrolled access to external scripts can be a serious security issue. But might not be if it is just you using it.

By default, code in function nodes cannot destroy your server - even if you've been foolish enough to run Node-RED as root. But external code certainly could. (as could function nodes if you included an external module without care).

Yes, of course, I've also said that. But you have to restart Node-RED if you want to pick up any changes.

All I am saying is that the ability to include external code dynamically within Node-RED can be a security issue and therefore needs some thought to make sure it can be properly controlled.

This is no different to ensuring a web site can't access arbitrary code and the reason that everyone (hopefully) understands that the eval function in JavaScript is possibly the most dangerous function. It is extremely powerful and occasionally useful - but it requires extreme care in use.

I'm not trying to stop such a thing being added, simply exposing the need for some caution.

I don't particularly get why re-using existing code (that you could already write in a function node) would be any more dangerous than ways that's already supported for making DIY js library on the fly (without needing to reload). Just like @sncgabb99 shows by adding functions to global context.

I've already explained.

Might be fine for your use, might not be fine in general.