Feature Request: Register JSONata function

I would like to be able to register JSONata functions. My use case: I want a simple wrapper around momment.js available in my JSONata expressions ... I can see how being able to register a JSONata function could make a good plugin/extension point for Node-Red.

I'm proposing three additions:

  • RED.util.registerJSONataFunction (name, function, signature="", snipt="")
  • RED.util.removeJSONataFunction (name)
  • RED.util.getJSONataFunctions() returns array of objects that have the functions and the meta-data for the functions for use in JSONata expressions

prepareJSONataExpression would have to be updated to call getJSONataFunctions (or maybe a helper function). Ideally the expr.assign and expr.registerFunction function calls in prepareJSONataExpression would be removed and registerJSONataFunction would be called for flowContext, globalContext, env & clone.

Notes:

  • I am assuming that in a follow up we would want update the JSONata editor to do a call a service to get the snipts for the registered functions so that they show along with the other functions in the editor
  • It might make sense if "removeJSONataFunction" replaced the function with a dummy function that logged an error ("JSONata function {name} has been removed") and updated the snipt so that it said something like "This function has been been removed." ... next time node red started it would be gone.

I would be willing to work on a pull request for this, and would be happy with any guidance or feedback.

2 Likes

Any feed back on this? I would be willing to work on a pull request for this, but I would probably need a bit of guidance on how best to add state to the RED.util object/namespace.

Thanks in advance for any feedback!

Hi @dustinw

how do you envisage this being used in general? Would node modules register the functions alongside any nodes they register? Would they be defined statically - ie as part of registering the module into the runtime - or that they could be added/removed dynamically whilst the flow is running?

If it's the static approach, where would removeJSONataFunction get used? At what point in the node lifecycle?

Or would these functions be registered through settings.js - much as you can add things to the Function node via functionGlobalContext. That would reduce the portability of flows that used custom functions - as they would rely on things in the settings file that don't get exported with the flow.

I think there is an interesting idea to pursue here - just need to explore how we'd expect it to be used which will help define the specific apis needed to support it.

I'm on vacation the rest of this week; I'll be online a bit, but replies may be a bit limited until next week.

That would be the primary use-case ... example: i.e. install the node-red-contrib-moment module and it installs some nodes and some JSONata functions. Uninstall that module and the additional JSONata functions go away.

I would like that to also be an option for advance users ... example: while I am waiting for my patch to be accepted to the node-red-contrib-moment module, I call the registerJSONataFunction in my settings.js file.

I might be missing something, but I think that would require an additional change: I don't see any events being emitted in the run-time during the start method that could be subscribed to (idealy we could subscribe to an on start event and an on Flowsloaded event).

I haven't fully reviewed the module lifecycle yet. I was trying to line it up to the design work in Design: Node module lifecycle · node-red/node-red Wiki · GitHub ... so in the module's remove function once it's available.

Thanks for your time! I hope you have a great vacation. I am looking forward to getting into this further once you have time.

Are there security concerns that need to be considered here - If these are globally registered functions - who can register them ? Will there be name collisions ? Can someone maliciously redefine a function ?

Great questions!

Regarding who can register them ... are there any controls on similar functions like "RED.httpAdmin.get/post/" & remove? It would be a similar risk level to those functions. I was assuming at this point that any nodes/modules added, and any code in the settings.js file would have to be trusted.

As for name collisions ... that would definitely be an issue. There are number of ways to handle it: I was originally assuming that we would either ignore any additional calls to registerJSONataFunction with the same Name (maybe logging a "$name is already defined" type warning), or just keep overwriting the same key with the updated function, but other options might be requiring some a module level prefix, or adding an incrementing suffix to the function name.

Would it make sense for me to start a pull request for this? We could further discuss this in the context of a pull request.

Thanks!

Hi @dustinw - I think we still need to iterate on the design and requirements before we starting reviewing any code changes.

We've being putting into place a bit more of a formalised way for design discussions around new features. The goal being to keep discussions in one place and help us to track what is being worked on that perhaps hasn't reached the point of having a code PR.

If you're willing to help test the process, please raise a PR against https://github.com/node-red/designs with a new proposal - the readme explains what to do. We can then use that PR to review and iterate on the proposal before any code is written.

Sure thing. That makes sense. I'll create a proposal following that process.

Minor suggestion: You should consider prefixing the repo name ... i.e. https://github.com/node-red/node-red-designs.