Function nodes - How to reuse JS functions in my functions?

Personally i find functions in global variables a bit obscure for a 'visual' programming tool. link-call nodes make it more visually clear, to me anyway

2 Likes

I agree, but that's not always very practical with function nodes, if you wanted to keep everything within the one function node node.

You could combine the approach with a single function node where you create a JS object in the startup tab that contains each of your functions. Then in the inbound msg, specify what fn to call (or even have a list). Output would be to msg.payload.

Fn Startup:

// globalThis is node.js's global scope
globalThis.myobject = {
   function myfn1(param1) {
      ....
   }
   ...
}

On msg:

msg.result = globalThis.myobject[msg.fnName](msg.param1)
return msg

Untested but I think it would work.

We really need a js library in node red, I've seen some successful examples in other low-code systems. All other alternatives are flawed.

1 Like

I get the desire, but I struggle with the concept. Because Node-RED is built using node.js. Node.js already has these capabilities baked right in.

As far as I can see, this thread has boiled down to 2 sides. Those who want something visual and those happy with combining code for utility functions.

If you are happy with code, there are already multiple ways to provide utility functions. Modules loaded in settings.js (the node.js way). Node-RED plugins. Functions assigned to in-memory context within flows on startup. Functions access via link calls.

The only thing that I see might slightly improve usability would be a standardised way to expose utility functions in function nodes. There is no official way at the moment, you can abuse the RED.util object but this is not ideal.

But none-the-less, you do already have multiple options.

1 Like

Interesting debate here!

After thinking it through, I'll definitely go with the Node.js module approach. There's one more detail I didn't mention before: I'm using multiple dockerized Node-RED instances and I want to share these functions across all my projects.

To keep them all updated to the latest version, I'll bind the module to Node-RED through a shared volume across containers and include it in all my settings.js files.

Just one concern: in the past, I've messed up settings.js in my containers and couldn't recover because the container failed to start, so I couldn't access it to fix the file. If I make a mistake in my module scripts, will the same thing happen? (Though if the module is volume-bound, I can correct it and relaunch the container, so not a huge problem.)

On the other hand, I totally agree with @TotallyInformation:

I'm struggling to think of anything in settings.js that would prevent the container from loading? Are you sure that was the issue, not something else?

But yes, if you have the userDir assigned to a bound volume then you can always manually edit it even if the container isn't running.

It is probably also best to keep the shared module in a separate bound volume so that you can independently secure it.

How is the concept difficult? You have a menu where you can add, edit, delete and otherwise organize code. Like code snippets. You already seen how users add functions to global context in order to share functions. Why can't the same be achieved as a robust, built-in way?

Modules require you to work outside node red. You must restart node red in order for them to take effect. If you want to edit the module, you can't do it inside node red.

Context is manual and brittle. You have to reserve first flow for function setup, because first flow is run first. These technical details which should be irrelevant when all you want is to share a code snippet.

Link calls are too limited. They require timeout, which is often irrelevant for the concept of a simple js library consisting of snippets. Personally I think they are hard to get a nice overview of. And you have to reserve space in flows for them. I'd rather push all lib code away to the side. I don't want them visible all the time in a flow.

Perhaps my favourite way at this moment would be to abuse the RED.util object in a way yeah.

Adding util snippets is such a nice to have comfort feature. Some languages have it built-in into the core. I remember C# had some way to add custom functions to primitives. Imagine having your own date formatting always available to all dates as a function!

Can show you examples of how this is used in big successful platforms like Thingsboard:

Here is js lib overview (can add, delete, edit):

Inside a js lib file, you can add the functions you want, super useful and absolute must-have here:

And finally, anywhere you work with js code, you have the modules button where you can select which modules from js library to use:

Imagine having this in node red!

1 Like

Yes, the issue was caused by an error in settings.js. I tried to enable adminAuth but accidentally left out a }, which broke the file and prevented the container from restarting.

This would definetly be superb! :eyes:

A simple validation I always do after changing my settings.js, is to open a command line and run node settings.js.
If there is a syntax error, it finds it and shows you exactly where.

2 Likes

Or an easy way to format a number?

Personally, I would have called that a bug in the container config. Failure to start a service dependency really should not prevent the container from starting. Otherwise, you have a very brittle configuration that all sorts of software, over which you may have no control, could end up with a denial of service.

I simply always edit it in VSCode with liniting turned on. :smiley: