Requiring a module from the modules used by Node RED

Right! here is the thing.
Now that Scorecards are a being displayed, I want to reduce my dependencies in package.json

I am sat at 8 - and one or 2 of them are not easily removable.

1 instance is express
I have a need to get access to the static middleware, so I can provide all the JS & CSS files for my custom UI tab.

And (unless I am incorrect) we can't create our own static middleware, unless requiring the express package?

So,
One way I believe is doable, is as follows.

const path = require('path');
const NodeRedPath = require.main.Module.path
const express =  require(path.combin(NodeRedPath,"../","express"));

I will be interested in some views with this method, it might actually offer a bit of safety with applying middleware from a different express version used in RED.httpAdmin

I dont have any experience in creating nodes but regarding serving static assets for your node
maybe you should look into Loading extra resources in the editor

2 Likes

Thanks @UnborN,

For someone not developing nodes - that's an awesome solution (and 1 I obviously didn't take advantage off during its debut)

will test this out - and will report back. :+1:

This is not the correct way to reference the ExpressJS app that Dashboard uses. All you need to do is take a reference to RED.httpNode. That is an Express Application object. That means that you can add new routers and middleware to it. You can also get a reference to Node-RED's http(s) server with RED.server.

Have a look at the vNext branch of uibuilder in nodes/libs/web.js around line 300 in the _webSetup function.


UPDATE: Sorry, I should also have said that you can just use express-static if you only want to add static folders.


That doesn't work at all I'm afraid.

const path          = require('path')
let x = Object.values(require.main.children)
let y = Object.values(x).filter( (child) => child.path.includes('express') )
console.log('>>>>', y[0].path )

returns something you can feed to require if you really want to do this. However, I'm not convinced about how robust that is. require can do some odd things at times. I'm also not sure it would work in an environment like IBM Cloudant either.

Hi @TotallyInformation

This is not the correct way to reference the ExpressJS app that Dashboard uses. All you need to do is take a reference to RED.httpNode

I'm using RED.httpAdmin to define some Administration based endpoints/services for node config value retrieval, the problem I had was being able to define my own static file middleware (one to instantiate the UI Tab JS File), so for this, I was requiring express, so I can create an instance of express.static myself, and apply that to RED.httpAdmin.use(...)

I apply some permissions on these endpoints, and from reading RED.auth.needsPermission can only be used with RED.httpAdmin?

these endpoints are also used to start processes that needs to be protected.

I hadn't been aware of the resource thing.
The answer given, actually changes this topic a little, meaning I don't need to dig into the modules to load express

all this, is to address some markers on my scorecard (dependency count) :laughing:

Yes, I already updated my answer to include the fact that you can install just express-static on its own, you don't need the whole of express just for that. The static middleware in express itself is, I believe, the same library.

Yes, that is correct.

If you need to do bespoke protection on Dashboard endpoints, I believe that custom middleware is probably the only way to do it. The only other realistic way is probably to use a reverse proxy and do the protection externally so avoiding any Node-RED complexities.

In my, admittedly limited, experience through developing uibuilder, trying to manhandle your way through require's innards is a frustrating and shaky experience. Best avoided if possible :slight_smile:

And here is the problem with scorecards. Over-optimisation for the sake of gamifying things.

Don't get me wrong, the scorecards are a useful addition to the flow library and for spotting some obvious (well they should have been! :rofl: ) problems with code written for Node-RED.

But personally, I wouldn't have included the number of package dependencies as an output. Some packages can be just a few lines of code but no less useful for that. And many node.js apps have dozens of dependencies and work amazingly well. Personally, I wouldn't have even reported it until the number got to 20 or so.

Has it been a long day? :wink:

This is my zwave node which has an integrated UI TAB within Node Red, it uses RED.httpAdmin for its communication with the main module.

I don't actually use Dashboard/uibuilder - I did many moons ago.

But personally, I wouldn't have included the number of package dependencies as an output. Some packages can be just a few lines of code but no less useful for that. And many node.js apps have dozens of dependencies and work amazingly well. Personally, I wouldn't have even reported it until the number got to 20 or so.

I concur

Every day is a looooong day in the NHS my friend. :tired_face:

The whole express discussion is redundant in this instance as the standard way (since 1.3) for nodes to provide additional resources is the resources folder as described in the first reply.

All of the rules are up for discussion, so if there's feedback, please do share so we can improve.

The package count check is certainly one that I'm not 100% sure about. I certainly understand what it is trying to do - highlight where there are a large number of dependencies because that increases the surface area of the node and any potential hidden security issues that are deep in the dependencies. How you square that with a pass/warn/fail type metric does mean you need scale to measure against.

This was the way - but more importantly, the correct way - thanks!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.