Developing nodes with external Node libraries

Hi,

UPDATE - Simplifying example to use “lodash”

I’m looking at building a custom node that uses lodash. I can build my custom node using n8n-node-dev, however when I run n8n I’m getting a 'Error: There was an error: Cannot find module ‘lodash’.

I’ve installed the module and exported (export NODE_FUNCTION_ALLOW_EXTERNAL=lodash) and then also installed its types.

Here’s what my code looks like:

import * as _ from "lodash";

import { IExecuteFunctions } from 'n8n-core';
import {
    INodeExecutionData,
    INodeType,
    INodeTypeDescription,
} from 'n8n-workflow';


export class Ven implements INodeType {
    description: INodeTypeDescription = {
    	    displayName: 'Venafi',
	   name: 'ven',
	   group: ['transform'],
	  version: 1,
	  description: 'Get certs from Ven',
	  defaults: {
	  	  name: 'Ven',
		  color: '#772244',
	  },
	  inputs: ['main'],
	  outputs: ['main'],
	  properties: [
	  	  // Node properties which the user gets displayed and
		 // can change on the node.
		  {
		  	  displayName: 'My String',
			  name: 'myString',
			type: 'string',
			default: '',
			placeholder: 'Placeholder value',
			description: 'The description text',
		}
	]
};


    async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {

	const items = this.getInputData();

	let item: INodeExecutionData;
	let myString: string
	

	// Itterates over all input items and add the key "myString" with the
	// value the parameter "myString" resolves to.
	// (This could be a different value for each item in case it contains an expression)
	for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
		myString = this.getNodeParameter('myString', itemIndex, '') as string;
		item = items[itemIndex];

		item.json['myString'] = _.toLower(myString);;
	}

	return this.prepareOutputData(items);

}

}

The variable NODE_FUNCTION_ALLOW_EXTERNAL is only meant for Function-Nodes and does not make any difference here.

For custom-nodes it simply matters which modules are available to n8n. So if you get the message that the module “lodash” can not be found it, seems like it is actually not available to n8n. So maybe it is not installed correctly after all. A simple test would be to start Node.js in the folder n8n is running from (where the actual code is) and then require the module from there. If it is available for Node.js there it should also be available for n8n and its nodes.

1 Like

Thanks. So I created a simple test script like this:

import * as _ from “lodash”;
const str = “HELLO THERE”
const low = _.toLower(str);
console.log(low)

And then ran it from the n8n dev directory, that works fine. However, when I try and run n8n from the same location it can’t find lodash.

Here’s the output:


npm run start 

> [email protected] start /Users/cbourne/development/n8ndev/n8n
> run-script-os


> [email protected] start:default /Users/cbourne/development/n8ndev/n8n
> cd packages/cli/bin && ./n8n

(node:75608) UnhandledPromiseRejectionWarning: Error: There was an error: Cannot find module 'lodash'
Require stack:
- /Users/cbourne/.n8n/custom/Venafi.node.js
- /Users/cbourne/development/n8ndev/n8n/packages/cli/dist/src/LoadNodesAndCredentials.js
- /Users/cbourne/development/n8ndev/n8n/packages/cli/dist/src/index.js
- /Users/cbourne/development/n8ndev/n8n/packages/cli/dist/commands/execute.js
- /Users/cbourne/development/n8ndev/n8n/node_modules/@oclif/config/lib/plugin.js
- /Users/cbourne/development/n8ndev/n8n/node_modules/@oclif/config/lib/config.js
- /Users/cbourne/development/n8ndev/n8n/node_modules/@oclif/config/lib/index.js
- /Users/cbourne/development/n8ndev/n8n/node_modules/@oclif/command/lib/command.js
- /Users/cbourne/development/n8ndev/n8n/node_modules/@oclif/command/lib/index.js
- /Users/cbourne/development/n8ndev/n8n/packages/cli/bin/n8n
    at Object.error (/Users/cbourne/development/n8ndev/n8n/node_modules/@oclif/errors/lib/index.js:22:17)
    at Start.error (/Users/cbourne/development/n8ndev/n8n/node_modules/@oclif/command/lib/command.js:59:23)
    at /Users/cbourne/development/n8ndev/n8n/packages/cli/commands/start.ts:197:10
(node:75608) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:75608) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

OK - so when I run “n8n-node-dev build” it compile my node and installs it into my “~/.n8n/custom” folder which doesn’t seem to be able to locate lodash. If I install lodash there then it works OK.

So should the “n8n-node-dev build” utility package the dependancies for my custom nodes ? or is there something else I should do ?

Carl

I think this’s a good point :ok_hand: :ok_hand: :ok_hand:
But still there’s a confusion :frowning: Because when build custom node it’s moved to ~/.n8n/custom dir (Where I have to run npm install?? in the first folder or ~/.n8n/custom??)
And finally what’s the difference between creating custom node like this way and cloning the n8n source code from github and create custom node inside it directly??

by the way, I run npm install amqplib in .n8n/custom dir and error is gone but code wont work yet… I just wanna be sure that i’m on right way

When I need to use custom libraries for custom nodes,

  1. Install the library in the directory that you develop in (this step needs for complication for ts using n8n-node-dev)
  2. Then install the library in ./n8n/custom

Then you are good to go!

But there is also one problem I am facing. As far as I understand n8n uses a recursive method that checks files in custom folder whether files ends with moduleName.node.js or not. In one of the libraries that I use there is also a file called msRest.node.js but has nothing to do with n8n. Is there anything that could prevent n8n from checking files from node_modules ?

That is actually not how it was intended. The ./n8n/custom folder is only for very simple nodes that you literally copy “compiled” in the folder.
That is what the n8n-node-dev is there for. It is a CLI you install on your system to make that easy.

You are not supposed to install any packages into the ./n8n/custom folder.

Here the documentation:
https://docs.n8n.io/nodes/creating-nodes/create-node.html#create-the-first-basic-node