How to use userDir

I am going to expose my lack of understanding of the Javascript model here.

I am trying to work on updating the fitbit node. I have discovered that where it is saving the credentials file, is not appropriate for using the node in the HomeAssistant addon (it seems to clean out the folder on each restart when loading the node from the config via git), so I think the right thing is to force it to save the file in the userDir, rather than using a hardcoded path (that can then fail).

I believe the way to get to this is to use RED.settings.get(userDir). Is this correct?

However, where I need to call this, I get an error saying effectively RED is not available.

As I said, I really do not fully understand the scoping of things in Javascript, so how can I expose this setting at this point in the code such that the file pat include the userDir?

You shouldn't be reading/writing files in userDir yourself. What exactly are you trying to do here?

Save the token credential file.

You should be storing that in the credentials store, not a separate file

Ok, how and where? Any pointers gratefully received.

As I said I have inherited most of this, a lot of this is new to me, but happy to adopt best practices if I possibly can.

Lets take a step back.

If this is storing Oauth tokens that are generated as a part of configuring the node in the editor, then they should be stored as credential properties on the node so they get stored properly.

If this is storing Oauth tokens that have to be periodically refreshed during runtime, then we don't have a solid solution for this today - there's an old issue on the backlog that covers the details.

The main issue is the storage layer of Node-RED is pluggable. This allows it to run in a cloud environment (for example) that cannot rely on a filesystem to be persistent, so you can plugin a database storage layer under Node-RED. So if a node was to read/write to the file system directly, it won't be a portable node.

There are early plans for a complete overhaul of the Storage API for the 3.0 release in April. This thread has reminded me we should look at providing a more generic get/set capability in that layer for nodes to use in scenarios like this.

It is storing Oauth tokens, created initially and refreshed periodically (which seems to work).

Precisely my issue. However, it should be reasonable to expect that the userDir is persistent.

If there is no good solution at present, can a solution be suggested such that I can use userDir for now?

The line you've linked to is outside of the function exported by the module which gets RED passed in.

If you want to use RED.settings.get('userDir') then do it inside the exported function. The easiest way to achieve that is to move the module.exports = function (RED) { line to the top of the file so everything is inside that function and RED is always in scope.

1 Like

Thanks - makes sense. I'll give that a go :slight_smile:

It should be relatively easy to put the storage code into a function so that you can switch between functions later on - therefore creating your own handler if needed. Of course, that would extend to using a function to wrap whatever Node-RED core ends up with. But if you needed to switch between the file system and, lets say Firebase for Google Cloud or maybe Cloudant for IBM cloud, that should be straight-forward.