# How to use external libraries?

**URL:** https://discourse.nodered.org/t/how-to-use-external-libraries/82279
**Category:** General
**Tags:** docker, function-node
**Created:** [23 October 2023 10:23 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279 "2023-10-23T10:23:49Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![jase](https://avatars.discourse-cdn.com/v4/letter/j/dbc845/32.png) [@jase](https://discourse.nodered.org/u/jase)
#### Post date: [23 October 2023 10:23 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/1 "2023-10-23T10:23:49Z")

</div>

Hi Community,

I'm trying to use the "mupdf-js" library in a function node (because mupdf offers more info than pdfjs).

To do so, I tried to follow the recommendations given in the thread # [Problem importing external libraries to node-red](https://discourse.nodered.org/t/problem-importing-external-libraries-to-node-red/70835). But still unsuccessfully.

What I did:  
a) install a docker container with a Debian OS and Node version 20.8.1

b) install in the container nodered `npm install -g node-red`

c) declare nodered as a service to be started on container start with `systemctl`

d) install "mupdf" with `npm install mupdf-js` in the node-red folder

e) modify settings.js section "functionGlobalContext" as follows:

```auto
    // The following property can be used to seed Global Context with predefined
    // values. This allows extra node modules to be made available with the
    // Function node.
    // For example,
    // functionGlobalContext: { os:require('os') }
    // can be accessed in a function block as:
    // global.get("os")
    functionGlobalContext: {
        mupdfJS:require('mupdf-js')
        // os:require('os'),
        // jfive:require("johnny-five"),
        // j5board:require("johnny-five").Board({repl:false})
    },

```

f) restart NodeRed

g) Create a function node  
g1) Declare "mupdf-js" as "mupdfJS" in the "SETUP" tab  
g2) in the "On Message" tab :

```auto
const mudf = global.get('mupdfJS');
var doc = new mupdf.Document.openDocument('filename.pdf','application/pdf');
msg.payload = doc;
return msg;

```

When launched, the flow returns  
`TypeError: Cannot read properties of undefined (reading 'Document')`

The logs of the Nodered service only showed:

```auto
[error] [function:muPDF] TypeError: mupdfJS is not a function

```

Any idea what step I'm missing?

---

<div class="post-metadata">

### Author: ![ralphwetzel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ralphwetzel/32/53713_2.png) [@ralphwetzel](https://discourse.nodered.org/u/ralphwetzel)
#### Post date: [23 October 2023 10:43 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/2 "2023-10-23T10:43:58Z")

</div>

> [@jase](#):
>
> ```auto
> const mudf = global.get('mupdfJS');
> var doc = new mupdf.Document.openDocument('filename.pdf','application/pdf');
> 
> ```

Looks like there's a typo in the first line. Shouldn't `mudf` be `mupdf`?

---

<div class="post-metadata">

### Author: ![jase](https://avatars.discourse-cdn.com/v4/letter/j/dbc845/32.png) [@jase](https://discourse.nodered.org/u/jase)
#### Post date: [23 October 2023 10:50 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/3 "2023-10-23T10:50:12Z")

</div>

Hi @ralphwetzel ,

You're right. This is however only a transcription mistake. You should read

```auto
const mupdf = global.get('mupdfJS');
var doc = new mupdf.Document.openDocument('filename.pdf', 'application/pdf');

```

Thx.

---

<div class="post-metadata">

### Author: ![ralphwetzel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ralphwetzel/32/53713_2.png) [@ralphwetzel](https://discourse.nodered.org/u/ralphwetzel)
#### Post date: [23 October 2023 11:19 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/4 "2023-10-23T11:19:28Z")

</div>

> [@jase](#):
>
> ```auto
> // The following property can be used to seed Global Context with predefined
> // values. This allows extra node modules to be made available with the
> // Function node.
> // For example,
> // functionGlobalContext: { os:require('os') }
> // can be accessed in a function block as:
> // global.get("os")
> functionGlobalContext: {
> mupdfJS:require('mupdf-js')
> 
> ```

`mupdf-js` seems to be an ES module. You thus would need to `import` it - not `require`!

Having done that, the [mupfd-js docu](https://github.com/andytango/mupdf-js#basic-usage) tells you:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/a/da25bd3b0005d960bb28009ffbd87741dc242432.png)

... which is different from what you're doing.

---

<div class="post-metadata">

### Author: ![jase](https://avatars.discourse-cdn.com/v4/letter/j/dbc845/32.png) [@jase](https://discourse.nodered.org/u/jase)
#### Post date: [23 October 2023 13:25 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/5 "2023-10-23T13:25:46Z")

</div>

Thanks for highlighting that fact. I'm however still unclear about the syntax to use.

**1** - I tried (already before) to use directly the code snippet from [mupdf-js - npm](https://www.npmjs.com/package/mupdf-js) you mentioned in the function node. But unsuccessful.

**2** - Now with your highlights, I tried it in slightly different way.

```auto
import { createMuPdf } from 'mupdf-js';
var file = msg.payload; // the pdf file is loaded with prior "read-file" node as a buffered array
const mupdf = createMuPdf();
const buf = file.arrayBuffer();
const doc = mupdf.load(buf);
msg.payload = doc;
return msg;

```

But I only got `"SyntaxError: Cannot use import statement outside a module (body:line 1)"`.

**3** - Same behaviour when declaring mupdf-js as `mupdfJS` in the Setup tab and replace in the first code line  
`import { createMuPdf } from mupdfJS;`

**4** - Same behaviour when using in `settings.js`

```auto
functionGlobalContext: {
        mupdfJS:import('mupdf-js')

```

**5** - When using

```auto
var file = msg.payload; // the pdf file is loaded with prior "read-file" node as a buffered array
const mupdf = mupdfJs.createMuPdf();
const buf = file.arrayBuffer();
const doc = mupdf.load(buf);
msg.payload = doc;
return msg;

```

the server is crashing !

A way out?

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [23 October 2023 13:31 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/6 "2023-10-23T13:31:24Z")

</div>

> [@jase](#):
>
> `mupdf-js`

Try adding `mupdf-js` to function node setup. Name it `mupdfJs` then see what it contains by doing `node.warn({mupdfJs})`

It is likely you will see `mupdfJs` contains `createMuPdf` as an object or function. Just expand it out in the debug node until you see `createMuPdf` as a function - that'll be what you use.

And in case it is not clear, `import` and `require` are not possible directly in the function node code. That's what the setup tab does.

---

<div class="post-metadata">

### Author: ![jase](https://avatars.discourse-cdn.com/v4/letter/j/dbc845/32.png) [@jase](https://discourse.nodered.org/u/jase)
#### Post date: [23 October 2023 14:00 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/7 "2023-10-23T14:00:32Z")

</div>

Hi @Steve-Mcl,

With `node.warn({mupdfJs});` the debug windows shows 2 functions associated with `mupdfJs`:

- `createMuPdf`
- `default`

When now using

```auto
var file = msg.payload;
const mupdf = mupdfJs.createMuPdf();
const doc = mupdf.load(file);
msg.payload = mupdf.getPageText(doc,0);
return msg;

```

the server crashes.

I tried several ways to invoke createMuPdf, but always resulting in a server crash.

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [23 October 2023 14:15 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/8 "2023-10-23T14:15:32Z")

</div>

> [@jase](#):
>
> `const mupdf = mupdfJs.createMuPdf();`

This, according to npm readme is async so you'll need to await it

```auto
await mupdfJs.createMuPdf()

```

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [23 October 2023 14:17 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/9 "2023-10-23T14:17:12Z")

</div>

Also, note, that module uses web assembly. You may need a newer version of node or a flag set to use web assembly. I've not tried.

Lastly, if you show us logs from around the time it crashes, we will be able to better help.

---

<div class="post-metadata">

### Author: ![jase](https://avatars.discourse-cdn.com/v4/letter/j/dbc845/32.png) [@jase](https://discourse.nodered.org/u/jase)
#### Post date: [24 October 2023 06:45 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/10 "2023-10-24T06:45:49Z")

</div>

Hi,

I inserted the async statement as follows:

```auto
const mupdf = await mupdfJs.createMuPdf();
const file = msg.payload;
const buf = file.arrayBuffer;
msg.payload = buf;
return msg;

```

It unfortunately resulted in a server crash again. Logs gave:

```auto
24 Oct 07:37:53 - [warn] Encrypted credentials not found
24 Oct 07:37:53 - [info] Server now running at http://127.0.0.1:1880/
24 Oct 07:37:53 - [info] Starting flows
24 Oct 07:37:53 - [info] Started flows
24 Oct 07:38:54 - [info] Stopping flows
24 Oct 07:38:54 - [info] Stopped flows
24 Oct 07:38:54 - [info] Updated flows
24 Oct 07:38:54 - [info] Starting flows
24 Oct 07:38:54 - [info] Started flows
TypeError: Failed to parse URL from /root/.node-red/node_modules/mupdf-js/dist/libmupdf.wasm
TypeError: Failed to parse URL from /root/.node-red/node_modules/mupdf-js/dist/libmupdf.wasm
24 Oct 07:38:57 - [red] Uncaught Exception:
24 Oct 07:38:57 - [error] RuntimeError: abort(TypeError: Failed to parse URL from /root/.node-red/node_modules/mupdf-js/dist/libmupdf.wasm). Build with -s ASSERTIONS=1 for more info.
    at process.abort (/root/.node-red/node_modules/mupdf-js/dist/libmupdf.js:9:13762)
    at process.emit (node:events:514:28)
    at emit (node:internal/process/promises:150:20)
    at processPromiseRejections (node:internal/process/promises:284:27)
    at process.processTicksAndRejections (node:internal/process/task_queues:96:32)

```

After some readings on the web, I decided to downgrade node.js version from 20.8.1 to 16.20.2. The flow doesn't crash anymore. A good start!

However, when starting that flow:

```auto
const mupdf = await mupdfJs.createMuPdf();
const file = msg.payload;
const doc = mupdf.load(file);

msg.payload = doc;
return msg;

```

The "doc" object returns empty.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/0/90c750e0f0be0365edcc458f1d74060d4c9591c5.png)

Looking at the logs again:

```auto
24 Oct 08:26:44 - [warn] Encrypted credentials not found
24 Oct 08:26:44 - [info] Server now running at http://127.0.0.1:1880/
24 Oct 08:26:44 - [info] Starting flows
24 Oct 08:26:44 - [info] Started flows
24 Oct 08:26:50 - [info] Stopping flows
24 Oct 08:26:50 - [info] Stopped flows
24 Oct 08:26:50 - [info] Updated flows
24 Oct 08:26:50 - [info] Starting flows
24 Oct 08:26:50 - [info] Started flows
24 Oct 08:27:33 - [info] Stopping flows
24 Oct 08:27:33 - [info] Stopped flows
24 Oct 08:27:33 - [info] Updated flows
24 Oct 08:27:33 - [info] Starting flows
24 Oct 08:27:33 - [info] Started flows
24 Oct 08:28:25 - [info] Stopping flows
24 Oct 08:28:25 - [info] Stopped flows
24 Oct 08:28:25 - [info] Updated flows
24 Oct 08:28:25 - [info] Starting flows
24 Oct 08:28:25 - [info] Started flows
error: cannot recognize xref format
warning: trying to repair broken xref
warning: repairing PDF document
error: zlib error: incorrect header check
warning: read error; treating as end of file
error: corrupt object stream (2 0 R)
warning: ignoring broken object stream (2 0 R)
error: zlib error: incorrect header check
warning: read error; treating as end of file
error: corrupt object stream (67 0 R)
warning: ignoring broken object stream (67 0 R)
24 Oct 08:29:18 - [info] Stopping flows
24 Oct 08:29:18 - [info] Stopped flows
24 Oct 08:29:18 - [info] Updated flows
24 Oct 08:29:18 - [info] Starting flows
24 Oct 08:29:18 - [info] Started flows
24 Oct 08:31:49 - [info] Stopping flows
24 Oct 08:31:49 - [info] Stopped flows
24 Oct 08:31:49 - [info] Updated flows
24 Oct 08:31:49 - [info] Starting flows
24 Oct 08:31:49 - [info] Started flows

```

The question is now if the buffered array provided by the "read file" node has an 8 bit buffer encoding as expected by mupdf.

If so, I may facing an issue specifically related to the mupdf-js library. What do you think?

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [24 October 2023 08:54 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/11 "2023-10-24T08:54:18Z")

</div>

> [@jase](#):
>
> What do you think?

What settings are in the file read node?

Have you checked this file can actually be read by the lib outside of Node-RED? (I.e. create a small node project that does the same thing - did it work on that file with current node version?)

---

<div class="post-metadata">

### Author: ![jase](https://avatars.discourse-cdn.com/v4/letter/j/dbc845/32.png) [@jase](https://discourse.nodered.org/u/jase)
#### Post date: [24 October 2023 12:40 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/12 "2023-10-24T12:40:19Z")

</div>

Hi,

Actually the file can be read outside NodeRed and can even be text extracted by the Python wrapping of muPDF (named fitz).

Settings in Read File node are as below:

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/c/fc9b83af38df8f86f3ca12e8220eca0df3bbeb27.png)

Ok if you managed to get it working. I'll start all over again with another file and new nodered instance. Keep you posted. Thanks.

---

<div class="post-metadata">

### Author: ![jase](https://avatars.discourse-cdn.com/v4/letter/j/dbc845/32.png) [@jase](https://discourse.nodered.org/u/jase)
#### Post date: [9 November 2023 16:22 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/13 "2023-11-09T16:22:57Z")

</div>

Hi @Steve-Mcl & @ralphwetzel ,

After quite a lot of struggle, I could make use of mupdf in Nodered. Let me share the issues encountered and the way I did.

(1) Using the `mupdf-js` package is in fact a known issue with WASM. Actually it did throw on my system a parsing error on `libmupdf.wasm` and made my Nodered instance crash.  
More info on [[FEATURE] Alternative way to instantiate mupdf-js instance · Issue #48 · andytango/mupdf-js · GitHub](https://github.com/andytango/mupdf-js/issues/48)

(2) As per recommendation in the previous link, I toggled to `mupdf` package.  
The function node had to be rewritten as follows:

```auto
const file = msg.payload;
const doc = mupdf.Document.openDocument(file, 'application/pdf');
msg.payload = doc.loadPage(0).toStructuredText().asJSON();
return msg;

```

From that node, I got a JSON object in `msg.payload` that can be then converted into an JS object with a JSON node as depicted below.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/f/ff2eb9be7abbcbd365ac3f8d519c8d94dba234e0.png)

As a result, I have the complete structured text object of mupdf.

Hope this may help you (and others).

Thanks again for the hints provided.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [8 January 2024 16:23 UTC](https://discourse.nodered.org/t/how-to-use-external-libraries/82279/14 "2024-01-08T16:23:19Z")

</div>

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