Problem loading an external module

sigh, but there MUST be a way to load that library - it's just plain JS...nothing fancy

If it is has no dependencies, copy the code into a function?

well, it's a lot - and I only need a few functions from it

What I could do - just to be able to continue developing - is to put everything in the "Start" section of a separate function node and define a global in there. Because I need functions from that lib in many of my nodes

Would that work in the sandbox?

There has been some thought/threads about named exports.

Tho I've not looked into it, I am certain it is possible. The function node uses dynamic import so with a little work, specifying destructured imports should be possible to essentially achieve const { something, somethingElse} = await import('some-lib') under the hood.

Need to check see if there is an open issue.

This is from your module, in rollup.config.js.

ok, sorry for bothering you, guys.

But I really have to stop here for today - will continue tomorrow!

Good night from Germany!

1 Like

Yes. But my preference is to make it a bit more visual by utilising link-call (visual subroutines) to make it visually re-usable

I'm not sure this is necessary - but anyway.
As it seems yet, the dynamic import currently only forwards the default export - and "fails" if this isn't present. That's a bit too focused - from my perspective. :wink:

I'm quite surprised, that none else had commented on this behavior before...

well, I have to admit that this is typical for me: whatever I'll touch will break...sorry!

I'm pretty sure it has. On the forum.

In the previous iteration of module support, it used CJS so you only got npm style imports. It was changed to use dynamic import, but it depends on the module being nice and returning a default.

What would you suggest? (I have gave it little thought that the off-the-top of my head response above)

I see - but that should be a dragon that's easy to kill...(albeit tomorrow)

Thanks for the hint!

Ok! :tada:
Here's what's happening:

The topic roots in the procedure used by Node-RED to determine the file to be imported for a given module.

In line 147, the require function (returned by createRequire) is asked to resolve(module) in the given moduleDir.
require - obviously - returns the CJS (require) file - not the ESM (import).

package.json states

require thus returns ./dist/javascript-interface-library.js.
import("./dist/javascript-interface-library.js") finally returns the empty namespace object already discovered earlier.

Yep, just been looking at that - however, that suggests the lib is supposed to support CJS, but has failed to export anything!

Am I missing something obvious?


EDIT

though i do acknowledge that even if we import the ESM, the fact Node-RED adds .default to the Function VM, it would still be undefined

That means nothing. It fails when you try to use it in a node.js app.

This is not a node-red issue but the fact that the library isn't working correctly with node.js

The feature for the function node is a convenience. If you need something more complex or different, add the library as a global in settings.js

:sigh: you seem to be making unwarranted assumptions about node-red. If you want more complex requirements than would be sensible and secure to allow in a function node - which uses node.js's virtual environment for security - you need to make use of the settings.js file or wrap the library in your own module so that it can be included. It is not the fault of Node-RED that javascript-interface-library is not using best practice for node.js modules.

Good morning!

After many experiments and 3 hours of hacking I finally copied all code from the old javascript-interface-library into a new package called node-red-javascript-interface-library which could then successfully be added to my function node's package import list.

While "copying" sounds really ugly, it allows me to proceed with my development, at least. I do not know which change finally led to success (I simply built an UMD, an ESM and an IIFE), but it works without touching the original library.

Thanks to all that helped investigating the problem!

Have a nice weekend!

To conclude this exchange:

The root cause for this problem stems from the fact that the export of symbols from javascript-interface-library.js fails. This is something that would needed to be fixed in the library (action @rozek).

Node-RED yet does a pretty good job importing those modules:
The file to be imported is resolved via require.resolve, which returns a cjs type module definition.
When calling import() for a cjs type module, its module.exports object is provided as the default export. Thus it is correct (!) to do

        sandbox[vname] = lib.default;

in 10-function.js, line 318.

What's happening now with node-red-javascript-interface-library and why does it work?
The procedure is (of course) the same. require.resolve resolves to node-red-javascript-interface-library.umd.js, import()ing this returns a non-empty namespace object with all module.exports put into default property. :+1:
NB: This confirms (from my perspective) that there's sth ... to be validated ... for javascript-interface-library.js!!

Final remark: Node-REDs import procedure is only of limited use (can't really say it fails) for ESM-only modules - as it's returning just the object defined by export default. For those modules, an improvement/fix seems to be necessary...

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