跳转至

构建声明式节点#

本教程将指导您构建声明式节点。在开始之前,请确保这是您需要的节点样式。有关更多信息,请参考选择节点构建方法

先决条件#

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

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

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

  • JavaScript/TypeScript
  • REST APIs
  • git

构建您的节点#

在本节中,您将克隆 n8n 的节点启动器仓库,并构建一个集成 NASA API 的节点。您将创建一个使用 NASA 的两个服务的节点:APOD(每日天文图片)和火星探测器照片。为了保持代码示例简短,该节点不会实现火星探测器照片端点的所有可用选项。

现有节点

n8n 有一个内置的 NASA 节点。为了避免与现有节点冲突,您需要为您的版本起一个不同的名称。

步骤 1:设置项目#

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

克隆仓库并导航到目录中:

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

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

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

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

nodes/NasaPics
nodes/NasaPics/NasaPics.node.json
nodes/NasaPics/NasaPics.node.ts
credentials/NasaPicsApi.credentials.ts

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

现在安装项目依赖项:

1
npm i

步骤 2:添加图标#

将 NASA SVG 徽标从这里保存为 nasapics.svgnodes/NasaPics/ 目录中。

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

不要引用 Font Awesome

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

步骤 3:创建节点#

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

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

步骤 3.1:导入#

首先添加 import 语句:

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

步骤 3.2:创建主类#

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

类名和文件名

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

1
2
3
4
5
6
7
8
export class NasaPics implements INodeType {
	description: INodeTypeDescription = {
		// Basic node details will go here
		properties: [
		// Resources and operations will go here
		]
	};
}

步骤 3.3:添加节点详情#

所有节点都需要一些基本参数,如显示名称、图标以及使用节点发出请求的基本信息。将以下内容添加到 description 中:

 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
displayName: 'NASA Pics',
name: 'NasaPics',
icon: 'file:nasapics.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Get data from NASAs API',
defaults: {
	name: 'NASA Pics',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
	{
		name: 'NasaPicsApi',
		required: true,
	},
],
requestDefaults: {
	baseURL: 'https://api.nasa.gov',
	headers: {
		Accept: 'application/json',
		'Content-Type': 'application/json',
	},
},

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

步骤 3.4:添加资源#

资源对象定义了节点使用的 API 资源。在本教程中,您将创建一个节点来访问 NASA 的两个 API 端点:planetary/apodmars-photos。这意味着您需要在 NasaPics.node.ts 中定义两个资源选项。使用资源对象更新 properties 数组:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
properties: [
	{
		displayName: 'Resource',
		name: 'resource',
		type: 'options',
		noDataExpression: true,
		options: [
			{
				name: 'Astronomy Picture of the Day',
				value: 'astronomyPictureOfTheDay',
			},
			{
				name: 'Mars Rover Photos',
				value: 'marsRoverPhotos',
			},
		],
		default: 'astronomyPictureOfTheDay',
	},
	// Operations will go here

]

type 控制 n8n 为资源显示的 UI 元素,并告诉 n8n 期望从用户获得什么类型的数据。options 会在 n8n 中添加一个下拉框,允许用户选择一个选项。有关更多信息,请参考节点 UI 元素

步骤 3.5:添加操作#

操作对象定义了资源上的可用操作。

在声明式节点中,操作对象包括 routing(在 options 数组内)。这设置了 API 调用的详情。

resource 对象之后,将以下内容添加到 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
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
{
	displayName: 'Operation',
	name: 'operation',
	type: 'options',
	noDataExpression: true,
	displayOptions: {
		show: {
			resource: [
				'astronomyPictureOfTheDay',
			],
		},
	},
	options: [
		{
			name: 'Get',
			value: 'get',
			action: 'Get the APOD',
			description: 'Get the Astronomy Picture of the day',
			routing: {
				request: {
					method: 'GET',
					url: '/planetary/apod',
				},
			},
		},
	],
	default: 'get',
},
{
	displayName: 'Operation',
	name: 'operation',
	type: 'options',
	noDataExpression: true,
	displayOptions: {
		show: {
			resource: [
				'marsRoverPhotos',
			],
		},
	},
	options: [
		{
			name: 'Get',
			value: 'get',
			action: 'Get Mars Rover photos',
			description: 'Get photos from the Mars Rover',
			routing: {
				request: {
					method: 'GET',
				},
			},
		},
	],
	default: 'get',
},
{
	displayName: 'Rover name',
	description: 'Choose which Mars Rover to get a photo from',
	required: true,
	name: 'roverName',
	type: 'options',
	options: [
		{name: 'Curiosity', value: 'curiosity'},
		{name: 'Opportunity', value: 'opportunity'},
		{name: 'Perseverance', value: 'perseverance'},
		{name: 'Spirit', value: 'spirit'},
	],
	routing: {
		request: {
			url: '=/mars-photos/api/v1/rovers/{{$value}}/photos',
		},
	},
	default: 'curiosity',
	displayOptions: {
		show: {
			resource: [
				'marsRoverPhotos',
			],
		},
	},
},
{
	displayName: 'Date',
	description: 'Earth date',
	required: true,
	name: 'marsRoverDate',
	type: 'dateTime',
	default:'',
	displayOptions: {
		show: {
			resource: [
				'marsRoverPhotos',
			],
		},
	},
	routing: {
		request: {
			// You've already set up the URL. qs appends the value of the field as a query string
			qs: {
				earth_date: '={{ new Date($value).toISOString().substr(0,10) }}',
			},
		},
	},
},
// Optional/additional fields will go here

这段代码创建了两个操作:一个用于获取今天的 APOD 图片,另一个用于发送 get 请求以获取某一个火星探测器的照片。名为 roverName 的对象要求用户选择他们想要获取照片的探测器。火星探测器操作中的 routing 对象引用这个选项来创建 API 调用的 URL。

步骤 3.6:可选字段#

大多数 API(包括您在本示例中使用的 NASA API)都有可选字段,您可以使用它们来精化查询。

为了避免给用户造成负担,n8n 在 UI 中在附加字段下显示这些字段。

对于本教程,您将添加一个附加字段,以允许用户选择与 APOD 端点一起使用的日期。将以下内容添加到 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
32
33
{
	displayName: 'Additional Fields',
	name: 'additionalFields',
	type: 'collection',
	default: {},
	placeholder: 'Add Field',
	displayOptions: {
		show: {
			resource: [
				'astronomyPictureOfTheDay',
			],
			operation: [
				'get',
			],
		},
	},
	options: [
		{
			displayName: 'Date',
			name: 'apodDate',
			type: 'dateTime',
			default: '',
			routing: {
				request: {
					// You've already set up the URL. qs appends the value of the field as a query string
					qs: {
						date: '={{ new Date($value).toISOString().substr(0,10) }}',
					},
				},
			},
		},
	],									
}

步骤 4:设置身份验证#

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

将以下内容添加到 nasaPicsApi.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
import {
	IAuthenticateGeneric,
	ICredentialType,
	INodeProperties,
} from 'n8n-workflow';

export class NasaPicsApi implements ICredentialType {
	name = 'NasaPicsApi';
	displayName = 'NASA Pics API';
	// Uses the link to this tutorial as an example
	// Replace with your own docs links when building your own nodes
	documentationUrl = 'https://docs.n8n.io/integrations/creating-nodes/build/declarative-style-node/';
	properties: INodeProperties[] = [
		{
			displayName: 'API Key',
			name: 'apiKey',
			type: 'string',
			default: '',
		},
	];
	authenticate = {
		type: 'generic',
		properties: {
			qs: {
				'api_key': '={{$credentials.apiKey}}'
			}
		},
	} as IAuthenticateGeneric;
}

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

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

关于您节点的元数据在节点根目录下的 JSON 文件中。n8n 称之为 codex 文件。在此示例中,文件为 NasaPics.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.NasaPics",
	"nodeVersion": "1.0",
	"codexVersion": "1.0",
	"categories": [
		"Miscellaneous"
	],
	"resources": {
		"credentialDocumentation": [
			{
				"url": ""
			}
		],
		"primaryDocumentation": [
			{
				"url": ""
			}
		]
	}
}

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

步骤 6:更新 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
{
	// All node names must start with "n8n-nodes-"
	"name": "n8n-nodes-nasapics",
	"version": "0.1.0",
	"description": "n8n node to call NASA's APOD and Mars Rover Photo services.",
	"keywords": [
		// This keyword is required for community nodes
		"n8n-community-node-package"
	],
	"license": "MIT",
	"homepage": "https://n8n.io",
	"author": {
		"name": "Test",
		"email": "[email protected]"
	},
	"repository": {
		"type": "git",
		// Change the git remote to your own repository
		// Add the new URL here
		"url": "git+<your-repo-url>"
	},
	"main": "index.js",
	"scripts": {
		// don't change
	},
	"files": [
		"dist"
	],
	// Link the credentials and node
	"n8n": {
		"n8nNodesApiVersion": 1,
		"credentials": [
			"dist/credentials/NasaPicsApi.credentials.js"
		],
		"nodes": [
			"dist/nodes/NasaPics/NasaPics.node.js"
		]
	},
	"devDependencies": {
		// don't change
	},
	"peerDependencies": {
		// don't change
	}
}

您需要更新 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

后续步骤#

此页面是否
💬 微信

🚀 与作者交流

关注公众号
n8n实战笔记公众号
n8n实战笔记
📚 教程 💡 案例 🔧 技巧
添加微信
添加作者微信
1对1 专业指导
⚡ 快答 🎯 定制 🚀 支持