Using modules with nodejs separate from NR?

In a different directory than NR, I tried installing a node module, separate from NR, # npm install . I got module not found using a require(''). So I did an uninstall, then global install of the module, # npm install -g . This resulted in EACCESS errors. What am I missing, are global install of modules not seen by node js? This lead me to the following qualification, https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally.

Is any of the above doing to break NR? Is NR variant of npm not installed with a version manager for npm?

There is no such thing as a node-red variant of npm. You have whatever version of npm you have. If you're using the Pi install script we provide, you'll have got whatever version of npm is packaged with the version of node.js that was installed.

Where was the code (relative to directory you ran the npm install in) that tried to do the require?

EACCESS means the process didn't have permission to write the files. This is because the global module location is typically somewhere that requires root access.

This article gives a complete explanation for how node tries to find something when you require it - https://www.freecodecamp.org/news/requiring-modules-in-node-js-everything-you-need-to-know-e7fbd119be8/

So node_modules under .node-red is a local repo, right? Modules in that 'dir tree' would be invisible to a require 'call' from some other directory not under .node-red, say /root for example, right? Thus npm run under .node-red is in 'effect' a local scope for npm. Especially if you do not use '-g' for npm installs in that directory. The npm command may be scope less, but what actions you take and where with npm do... in fact create a scope. This why you can end up with 'nobody' ownership, why you can end up with EACCESS errors. Right?

npm (not -g) installs to the current directory (ie node_modules is in the current directory). npm -g installs to a system location and on Linux will generally require sudo to write there, that is why you got the access permission error (you didn't use sudo). On linux generally it is either sudo npm -g install or npm install (no sudo, no -g).

Globally installed nodes will be available from anywhere in the system, locally installed ones are available only from the directory where they were installed.

Cool. Thanks for details. Just seemed odd a module installed with -g using root, could get an EACCESS error.

This is good not odd. Global installs need root to install but not necessarily to run. That's because of the fact that global installs need write access to system folders. Read/execute access is then available to all.

So global installs are protected from change by ordinary users.

In general though, global installs of npm modules should be avoided since they can introduce unexpected security issues.

I had missed the fact that you said you ran npm as root. Can you repeat that and post the resulting output please?

Rats... I reset the environment.. If I get the chance will try to recreate the scenario.

Moreover, I still see module not found issues for odd reasons in just using node. Google is just buried in issues and possible fixes to when or how node modules are not found, the prefix is wrong, or the NODE_PATH variable not set, the list of potential pit falls is extensive.

I have for now, just restored to using absolute paths. This is not a NR issue, as long as NR modules are placed under .node-red/node_modules, no issues.

It is when I am writing code under just node to get i2c, spi, etc. communication right, or code logic finalized, and once the code is solid, only then dropping it in or wrapping it up for NR.

I am developing a true love/hate relationship with npm.

1 Like

Another question... is there a way to programmatically determine if code is running under NR versus just node? It would be cool if I could use console.log() versus node.log() at the appropriate time... using just node in writing the bulk of the code logic, for me, is faster than loading it into NR over and over.

Probably yes but a simple way would be to use an env variable e.g....

process.env.WITHOUTNODERED

If you determine you are NOT in node-red, then you could set node.xxxx functions to proxy functions instead of littering your code with if(isNodeRed) node.log(X) else console.log(X)

More info on env vars...

Maybe it could simply be declaring:

var node = node ? node : {
  log: console.log,
  error: console.error,
  warn: console.warn,
  debug: console.debug,
  trace: console.trace
};

The unneeded log functions could be left out and that made into a simple one liner:

var node = node ? node : { log: console.log, error: console.error, warn: console.warn };

This seemed to work both on node and a function node due to using var. With const I got an error on the function node as node is already declared.

1 Like

As I typed that from my mobile i thought it easier than asking if node was defined as often var node = this is written in custom nodes - so calling var node = node ? node : { log: console.log, error: console.error, warn: console.warn }; may have failed due to node === this regardless of whatever this is.

(few, hope that ^ made sense!)

I dont have time to run up a custom node-red contrib node and find a simple means of understanding if I took the red pill or blue pill so suggested a sure fire way of knowing via an explicit env var (if you set it - then its true right!).

PS, I'm bookmarking that nice snippet (because I always forget how that var xxx = { yyy, zzz} syntax works - just cant seem to commit it to memory (I used to struggle with arrow functions syntax too :wink: !)

1 Like

Yep don't know about custom nodes, this was only for function nodes and plain CLI node.js.

Actually for this use case this could be further simplified to just:

var node = node ? node : console;

Naturally you'd need to be careful not to use any node or console specific functions to maintain compatibility both ways.

Ah yes, anyone who has to wrangle with npm eventually ends up in that place!

There are many ways and it somewhat depends where you want to determine that. In most cases, if the object RED exists, you can be pretty sure that you are running under Node-RED. But of course, there are places in code when that won't be available. and in that case, you can use node.js's process module to find out what executable started the current process.

1 Like

This is just to allow easy code development, debugging, so does not need to be complex or robust, the console references would be stripped from code as development cycle comes to a close. I typically have a helper function that does exception/status reporting, so easy to check each time I would call .log,, .debug, etc.