05. Node 与 Credential:扩展系统的两张表
5.1 一个节点由 description 和 implementation 组成
以 Webhook、HttpRequest、Code 等官方节点为例,它们通常包含:
Node package
├── *.node.json # 节点元数据、图标、入口、版本等
├── *.node.ts # INodeType / INodeTypeDescription + execute
├── descriptions/ # 参数 UI schema 与显示条件
├── methods/ # loadOptions、resourceLocator、credentialTest
└── test/ # 节点和 workflow fixture
INodeTypeDescription 是编辑器的 schema:名称、分类、输入输出、properties、credentials、displayOptions、version。execute() 是运行时实现。编辑器只需要 description 就能渲染参数面板,执行器只需要 type class 就能运行,因此 UI 与节点执行可以相对独立。
5.2 节点加载器
packages/core/src/nodes-loader 负责扫描目录、发现 package、隔离加载 class、校验 description、处理自定义目录和热加载。典型路径:
directory-loader.ts:加载一组节点目录。package-directory-loader.ts:按 npm package 识别节点包。custom-directory-loader.ts:加载用户/社区扩展目录。validate-node-description.ts:保证描述满足运行时假设。
加载结果可以看成两个索引:
nodeTypeName → INodeTypeData { type, sourcePath }
credentialTypeName → ICredentialType
执行时按 workflow 中的 node.type 找到 type class,编辑器通过 /types/nodes.json 等接口拿到 description。
5.3 Credential 不是节点参数
节点 JSON 只保存 credential 的类型与 id/name 引用,真正的 secret 由 credential service 和 repository 管理。执行时的链路是:
node.credentials reference
→ CredentialsHelper.getCredentials()
→ 解密 / 外部 secret provider / dynamic proxy
→ credential type authenticate()
→ request options
packages/cli/src/credentials-helper.ts 还处理 declarative authentication、OAuth token 刷新、表达式解析、凭证覆盖和连接测试。节点只调用 this.helpers.httpRequestWithAuthentication() 一类能力,不应自行读取数据库中的密文。
5.4 三种节点行为
| 行为 | 典型入口 | 运行时意义 |
|---|---|---|
| 普通 action | execute() | 输入 item → 输出 item |
| trigger / poll | trigger()、poll() | 产生新的 workflow execution |
| AI supply data | supplyData() | 向 AI 根节点提供模型、memory 或 tool |
同一个 node description 可以声明多种输入/输出类型。AI 节点尤其依赖非 main connection,因此 description、编辑器端口和执行器遍历必须一致。
5.5 版本与社区节点
官方节点经常保留 v1、v2、v3 子目录,并通过 versioned node type 选择实现。这样可以让新版本参数和行为演进,同时保留旧工作流的可执行性。packages/node-dev 提供创建和构建节点的开发工具;packages/@n8n/scan-community-package、ESLint 插件和加载校验负责降低社区包把危险代码或不兼容 schema 带进来的风险。
5.6 用一个 HTTP 节点阅读法练习
阅读 packages/nodes-base/nodes/HttpRequest 时按以下顺序:
- 看
HttpRequest.node.json:入口、图标和打包信息。 - 看
HttpRequest.node.ts:类如何组合 description 和 execute。 - 看
V3/Description.ts:resource/operation 参数如何决定 UI。 - 看
packages/core/src/node-execute-functions.ts:请求、凭证、表达式和 binary helper 如何注入。 - 看测试:错误、分页、OAuth 和响应解析如何被固定下来。
5.7 设计取舍
schema 驱动 UI让集成节点不必为每个参数手写前端组件;代价是 schema 的表达能力、可读性和版本兼容性成为长期负担。
credential helper 统一认证减少节点重复代码,也形成了集中安全边界;代价是特殊 OAuth、动态 credential 和表达式凭证会把 helper 变成高复杂度模块。
按版本保留节点实现保护旧工作流;代价是节点包中同时存在多套逻辑,重构时必须明确兼容策略。