构建声明式节点#
本教程将指导您构建一个声明式节点。开 始之前,请确认这是您需要的节点样式。更多信息请参考选择节点构建方法。
前置要求#
您的开发环境需要安装以下组件:
- git
- Node.js 和 npm。最低版本要求 Node 18.17.0。Linux、Mac 和 WSL 用户可参考此指南通过 nvm(Node版本管理器)安装。Windows 用户请参阅微软的Windows系统NodeJS安装指南。
需要具备以下知识基础:
- JavaScript/TypeScript
- REST API
- git
构建节点#
本节将指导您克隆n8n节点入门仓库,并构建一个集成NASA API的节点。您将创建使用NASA两项服务的节点:APOD(每日天文图)和火星探测器照片服务。为保持代码示例简洁,该节点不会实现火星探测器照片端点的所有可用选项。
现有节点说明
n8n已内置NASA节点。为避免与现有节点冲突,您需要为新版本指定不 同名称。
步骤1:项目设置#
n8n为节点开发提供了入门仓库。使用该模板可确保获得所有必要依赖,同时包含代码检查工具。
克隆仓库并进入目录:
- 基于模板仓库生成新仓库
- 克隆您的新仓库:
git clone https://github.com/<your-organization>/<your-repo-name>.git n8n-nodes-nasa-pics cd n8n-nodes-nasa-pics
启动器包含示例节点和凭据。请删除以下目录和文件:
nodes/ExampleNodenodes/HTTPBincredentials/ExampleCredentials.credentials.tscredentials/HttpBinApi.credentials.ts
现在创建以下目录和文件:
nodes/NasaPics
nodes/NasaPics/NasaPics.node.json
nodes/NasaPics/NasaPics.node.ts
credentials/NasaPicsApi.credentials.ts
这些是任何节点所需的关键文件。有关必需文件和推荐组织的更多信息,请参阅节点文件结构。
现在安装项目依赖项:
npm i
步骤2:添加图标#
将NASA SVG徽标从此处另存为 nasapics.svg 至 nodes/NasaPics/ 目录。
n8n推荐使用SVG格式作为节点图标,但也可使用PNG格式。若使用PNG格式,图标分辨率应为60x60像素。节点图标应保持正方形或接近正方形的宽高比。
禁止引用Font Awesome
如需在节点中使用Font Awesome图标,请下载并嵌入图像文件。
步骤3:创建节点#
每个节点必须包含基础文件。有关基础文件参数的详细信息,请参阅节点基础文件。
本示例中文件命名为 NasaPics.node.ts。为简化本教程,所有节点功能将集中在此单一文件中。开发更复杂的节点时,建议将功能拆分至不同模块。更多信息请参阅节点文件结构。
步骤3.1:导入声明#
首先添加导入声明:
import { INodeType, INodeTypeDescription } from 'n8n-workflow';
步骤 3.2:创建主类#
节点必须导出一个实现 INodeType 的接口。该接口必须包含 description 接口,而该接口又需包含 properties 数组。
类名与文件名规范
请确保类名与文件名保持一致。例如,若类名为 NasaPics,则文件名必须为 NasaPics.node.ts。
export class NasaPics implements INodeType {
description: INodeTypeDescription = {
// Basic node details will go here
properties: [
// Resources and operations will go here
]
};
}
步骤 3.3:添加节点详细信息#
所有节点都需要一些基本参数,例如其显示名称、图标以及使用该节点发起请求的基本信息。请将以下内容添加到 description 中:
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 中设置的某些属性在编辑器界面中渲染节点。这些属性包括 displayName、icon、description 和 subtitle。
步骤 3.4:添加资源#
资源对象定义了节点所使用的 API 资源。在本教程中,您将创建一个用于访问 NASA 两个 API 端点(planetary/apod 和 mars-photos)的节点。这意味着您需要在 NasaPics.node.ts 中定义两个资源选项。请使用资源对象更新 properties 数组:
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:添加操作#
操作对象定义了资源可用的操作。
在声明式节点中,操作对象包含位于 options 数组内的 routing 配置。该配置用于设置 API 调用的详细信息。
请将以下内容添加至 properties 数组中,紧随 resource 对象之后:
{
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在界面中将这类字段归类在附加字段区域显示。
在本教程中,您将添加一个附加字段,允许用户为APOD接口选择特定日期。请将以下内容添加到属性数组中:
{
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 文件中:
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将其称为法典文件。本示例中的文件为NasaPics.node.json。
将以下代码添加至JSON文件:
{
"node": "n8n-nodes-base.NasaPics",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": [
"Miscellaneous"
],
"resources": {
"credentialDocumentation": [
{
"url": ""
}
],
"primaryDocumentation": [
{
"url": ""
}
]
}
}
有关这些参数的更多信息,请参阅节点编录文件。
步骤6:更新npm包详细信息#
您的npm包详细信息位于项目根目录的package.json文件中。必须包含带有凭据和基础节点文件链接的n8n对象。请更新此文件以包含以下信息:
{
// 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": "test@example.com"
},
"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实例中运行节点来边开发边测试。
- 使用npm安装n8n:
npm install n8n -g
- 当您准备好测试节点时,请将其在本地发布:
# In your node directory
npm run build
npm link
- 将节点安装到本地 n8n 实例中:
# In the nodes directory within your n8n installation
# node-package-name is the name from the package.json
npm link <node-package-name>
检查目录
确保在您的 n8n 安装目录中的 nodes 文件夹下运行 npm link <node-name>。该目录可能是:
~/.n8n/custom/~/.n8n/<your-custom-name>:如果您的 n8n 安装通过N8N_CUSTOM_EXTENSIONS设置了不同名称。
- 启动 n8n:
n8n start
-
在浏览器中打开n8n。在节点面板中搜索时应能看到您的节点。
节点名称说明
请确保使用节点名称而非包名称进行搜索。例如:若您的npm包名为
n8n-nodes-weather-nodes,且该包包含名为rain、sun、snow的节点,则应搜索rain而非weather-nodes。
故障排除#
若本地安装的~/.n8n目录中不存在custom文件夹,需手动创建custom目录并执行npm init命令:
# In ~/.n8n directory
run mkdir custom
cd custom
npm init