Skip to content

构建编程式节点#

本教程介绍如何构建编程式节点。在开始之前,请确保这是您需要的节点样式。参考选择您的节点构建方法了解更多信息。

前置条件#

您需要在开发机器上安装以下内容:

  • git
  • Node.js 和 npm。最低版本 Node 18.17.0。您可以在这里找到使用 nvm(Node 版本管理器)为 Linux、Mac 和 WSL 安装两者的说明。对于 Windows 用户,请参考 Microsoft 的在 Windows 上安装 NodeJS 指南。

您需要对以下内容有一定了解:

  • JavaScript/TypeScript
  • REST API
  • git
  • n8n 中的表达式

构建您的节点#

在本节中,您将克隆 n8n 的节点启动器仓库,并构建一个集成 SendGrid 的节点。您将创建一个实现 SendGrid 功能的节点:创建联系人。

现有节点

n8n 有一个内置的 SendGrid 节点。为了避免与现有节点冲突,您将为您的版本提供不同的名称。

步骤 1:设置项目#

n8n 为节点开发提供了一个启动器仓库。使用启动器确保您拥有所有必要的依赖项。它还提供了一个检查器。

克隆仓库并导航到目录:

  1. 从模板仓库生成新仓库
  2. 克隆您的新仓库:
    1
    2
    git clone https://github.com/<your-organization>/<your-repo-name>.git n8n-nodes-friendgrid
    cd n8n-nodes-friendgrid
    

启动器包含示例节点和凭据。删除以下目录和文件:

  • nodes/ExampleNode
  • nodes/HTTPBin
  • credentials/ExampleCredentials.credentials.ts
  • credentials/HttpBinApi.credentials.ts

现在创建以下目录和文件:

nodes/FriendGrid
nodes/FriendGrid/FriendGrid.node.json
nodes/FriendGrid/FriendGrid.node.ts
credentials/FriendGridApi.credentials.ts

这些是任何节点所需的关键文件。参考节点文件结构了解更多关于必需文件和推荐组织的信息。

现在安装项目依赖项:

1
npm i

步骤 2:添加图标#

这里保存 SendGrid SVG 徽标,作为 friendGrid.svg 保存在 nodes/FriendGrid/ 中。

n8n 建议为您的节点图标使用 SVG 格式,但您也可以使用 PNG。如果使用 PNG,图标分辨率应为 60x60px。节点图标应具有正方形或接近正方形的宽高比。

不要引用 Font Awesome

如果您想在节点中使用 Font Awesome 图标,请下载并嵌入图像。

步骤 3:在基础文件中定义节点#

每个节点都必须有一个基础文件。参考节点基础文件了解基础文件参数的详细信息。

在这个示例中,文件是 FriendGrid.node.ts。为了保持本教程简短,您将把所有节点功能放在这一个文件中。在构建更复杂的节点时,您应该考虑将功能拆分到模块中。参考节点文件结构了解更多信息。

步骤 3.1:导入#

首先添加导入语句:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import {
	IExecuteFunctions,
} from 'n8n-core';

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

import {
	OptionsWithUri,
} from 'request';

步骤 3.2:创建主类#

节点必须导出一个实现 INodeType 的接口。此接口必须包含一个 description 接口,该接口又包含 properties 数组。

类名和文件名

确保类名和文件名匹配。例如,给定类 FriendGrid,文件名必须是 FriendGrid.node.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
export class FriendGrid implements INodeType {
	description: INodeTypeDescription = {
		// 基本节点详细信息将放在这里
		properties: [
			// 资源和操作将放在这里
		],
	};
	// 执行方法将放在这里
	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
	}
}

步骤 3.3:添加节点详细信息#

所有编程式节点都需要一些基本参数,如显示名称和图标。将以下内容添加到 description 中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
displayName: 'FriendGrid',
name: 'friendGrid',
icon: 'file:friendGrid.svg',
group: ['transform'],
version: 1,
description: 'Consume SendGrid API',
defaults: {
	name: 'FriendGrid',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
	{
		name: 'friendGridApi',
		required: true,
	},
],

n8n 使用 description 中设置的一些属性在编辑器 UI 中渲染节点。这些属性是 displayNameicondescription

步骤 3.4:添加资源#

资源对象定义节点使用的 API 资源。在本教程中,您正在创建一个节点来访问 SendGrid 的 API 端点之一:/v3/marketing/contacts。这意味着您需要为此端点定义一个资源。使用资源对象更新 properties 数组:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
	displayName: 'Resource',
	name: 'resource',
	type: 'options',
	options: [
		{
			name: 'Contact',
			value: 'contact',
		},
	],
	default: 'contact',
	noDataExpression: true,
	required: true,
	description: 'Create a new contact',
},

type 控制 n8n 为资源显示哪个 UI 元素,并告诉 n8n 期望用户提供什么类型的数据。options 导致 n8n 添加一个允许用户选择一个选项的下拉菜单。参考节点 UI 元素了解更多信息。

步骤 3.5:添加操作#

操作对象定义您可以对资源执行的操作。它通常与 REST API 动词(GET、POST 等)相关。在本教程中,有一个操作:创建联系人。它有一个必需字段,即用户创建的联系人的电子邮件地址。

将以下内容添加到 properties 数组中,在 resource 对象之后:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
	displayName: 'Operation',
	name: 'operation',
	type: 'options',
	displayOptions: {
		show: {
			resource: [
				'contact',
			],
		},
	},
	options: [
		{
			name: 'Create',
			value: 'create',
			description: 'Create a contact',
			action: 'Create a contact',
		},
	],
	default: 'create',
	noDataExpression: true,
},
{
	displayName: 'Email',
	name: 'email',
	type: 'string',
	required: true,
	displayOptions: {
		show: {
			operation: [
				'create',
			],
			resource: [
				'contact',
			],
		},
	},
	default:'',
	placeholder: '[email protected]',
	description:'Primary email for the contact',
},

步骤 3.6:添加可选字段#

大多数 API,包括您在此示例中使用的 SendGrid API,都有可选字段,您可以使用这些字段来优化查询。

为了避免让用户感到不知所措,n8n 在 UI 中的附加字段下显示这些字段。

对于本教程,您将添加两个附加字段,以允许用户输入联系人的名字和姓氏。将以下内容添加到 properties 数组:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
	displayName: 'Additional Fields',
	name: 'additionalFields',
	type: 'collection',
	placeholder: 'Add Field',
	default: {},
	displayOptions: {
		show: {
			resource: [
				'contact',
			],
			operation: [
				'create',
			],
		},
	},
	options: [
		{
			displayName: 'First Name',
			name: 'firstName',
			type: 'string',
			default: '',
		},
		{
			displayName: 'Last Name',
			name: 'lastName',
			type: 'string',
			default: '',
		},
	],
},

步骤 4:添加执行方法#

您已经设置了节点 UI 和基本信息。现在是时候将节点 UI 映射到 API 请求,并让节点实际执行某些操作了。

execute 方法在每次节点运行时运行。在此方法中,您可以访问输入项目和用户在 UI 中设置的参数,包括凭据。

将以下内容添加到 FriendGrid.node.ts 中的 execute 方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 处理来自前一个节点的数据
const items = this.getInputData();
let responseData;
const returnData = [];
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;

// 对于每个项目,进行 API 调用以创建联系人
for (let i = 0; i < items.length; i++) {
	if (resource === 'contact') {
		if (operation === 'create') {
			// 获取电子邮件输入
			const email = this.getNodeParameter('email', i) as string;
			// 获取附加字段输入
			const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
			const data: IDataObject = {
				email,
			};

			Object.assign(data, additionalFields);

			// 根据 https://sendgrid.com/docs/api-reference/ 进行 HTTP 请求
			const options: OptionsWithUri = {
				headers: {
					'Accept': 'application/json',
				},
				method: 'PUT',
				body: {
					contacts: [
						data,
					],
				},
				uri: `https://api.sendgrid.com/v3/marketing/contacts`,
				json: true,
			};
			responseData = await this.helpers.requestWithAuthentication.call(this, 'friendGridApi', options);
			returnData.push(responseData);
		}
	}
}
// 将数据映射到 n8n 数据结构
return [this.helpers.returnJsonArray(returnData)];

注意此代码的以下行:

1
2
3
4
5
6
7
const items = this.getInputData();
... 
for (let i = 0; i < items.length; i++) {
	...
	const email = this.getNodeParameter('email', i) as string;
	...
}

用户可以通过两种方式提供数据:

  • 直接在节点字段中输入
  • 通过映射工作流中早期节点的数据

getInputData() 和随后的循环允许节点处理数据来自前一个节点的情况。这包括支持多个输入。这意味着,例如,如果前一个节点输出五个人的联系信息,您的 FriendGrid 节点可以创建五个联系人。

步骤 5:设置身份验证#

SendGrid API 要求用户使用 API 密钥进行身份验证。

将以下内容添加到 FriendGridApi.credentials.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import {
	IAuthenticateGeneric,
	ICredentialTestRequest,
	ICredentialType,
	INodeProperties,
} from 'n8n-workflow';

export class FriendGridApi implements ICredentialType {
	name = 'friendGridApi';
	displayName = 'FriendGrid API';
	properties: INodeProperties[] = [
		{
			displayName: 'API Key',
			name: 'apiKey',
			type: 'string',
			default: '',
		},
	];

	authenticate: IAuthenticateGeneric = {
		type: 'generic',
		properties: {
			headers: {
				Authorization: '=Bearer {{$credentials.apiKey}}',
			},
		},
	};

	test: ICredentialTestRequest = {
		request: {
			baseURL: 'https://api.sendgrid.com/v3',
			url: '/marketing/contacts',
		},
	};
}

有关凭据文件和选项的更多信息,请参考凭据文件

步骤 6:添加节点元数据#

关于您节点的元数据放在节点根目录的 JSON 文件中。n8n 将此称为代码库文件。在此示例中,文件是 FriendGrid.node.json

将以下代码添加到 JSON 文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
	"node": "n8n-nodes-base.FriendGrid",
	"nodeVersion": "1.0",
	"codexVersion": "1.0",
	"categories": [
		"Miscellaneous"
	],
	"resources": {
		"credentialDocumentation": [
			{
				"url": ""
			}
		],
		"primaryDocumentation": [
			{
				"url": ""
			}
		]
	}
}

有关这些参数的更多信息,请参考节点代码库文件

步骤 7:更新 npm 包详细信息#

您的 npm 包详细信息在项目根目录的 package.json 中。包含带有凭据和基础节点文件链接的 n8n 对象是至关重要的。更新此文件以包含以下信息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
	// 所有节点名称必须以 "n8n-nodes-" 开头
	"name": "n8n-nodes-friendgrid",
	"version": "0.1.0",
	"description": "n8n node to create contacts in SendGrid",
	"keywords": [
		// 社区节点需要此关键字
		"n8n-community-node-package"
	],
	"license": "MIT",
	"homepage": "https://n8n.io",
	"author": {
		"name": "Test",
		"email": "[email protected]"
	},
	"repository": {
		"type": "git",
		// 将 git 远程更改为您自己的仓库
		// 在此添加新 URL
		"url": "git+<your-repo-url>"
	},
	"main": "index.js",
	"scripts": {
		// 不要更改
	},
	"files": [
		"dist"
	],
	// 链接凭据和节点
	"n8n": {
		"n8nNodesApiVersion": 1,
		"credentials": [
			"dist/credentials/FriendGridApi.credentials.js"
		],
		"nodes": [
			"dist/nodes/FriendGrid/FriendGrid.node.js"
		]
	},
	"devDependencies": {
		// 不要更改
	},
	"peerDependencies": {
		// 不要更改
	}
}

您需要更新 package.json 以包含您自己的信息,如您的姓名和仓库 URL。有关 npm package.json 文件的更多信息,请参考 npm 的 package.json 文档

测试您的节点#

您可以通过在本地 n8n 实例中运行来测试正在构建的节点。

  1. 使用 npm 安装 n8n:
    1
    npm install n8n -g
    
  2. 当您准备测试节点时,在本地发布它:
    1
    2
    3
    # 在您的节点目录中
    npm run build
    npm link
    
  3. 将节点安装到您的本地 n8n 实例中:

    1
    2
    3
    # 在您的 n8n 安装目录中的 nodes 目录中
    # node-package-name 是来自 package.json 的名称
    npm link <node-package-name>
    

    检查您的目录

    确保您在 n8n 安装目录中的 nodes 目录中运行 npm link <node-name>。这可以是:

    • ~/.n8n/custom/
    • ~/.n8n/<your-custom-name>:如果您的 n8n 安装使用 N8N_CUSTOM_EXTENSIONS 设置了不同的名称。
  4. 启动 n8n:

    1
    n8n start
    

  5. 在浏览器中打开 n8n。当您在节点面板中搜索时,应该能看到您的节点。

    节点名称

    确保您使用节点名称搜索,而不是包名称。例如,如果您的 npm 包名称是 n8n-nodes-weather-nodes,并且包含名为 rainsunsnow 的节点,您应该搜索 rain,而不是 weather-nodes

故障排除#

  • ~/.n8n 本地安装中没有 custom 目录。

您必须手动创建 custom 目录并运行 npm init

1
2
3
4
# 在 ~/.n8n 目录中运行
mkdir custom 
cd custom 
npm init

下一步#