Novu Framework Controls:用Schema让非技术人员修改工作流内容
2026/9/10 5:52:31 网站建设 项目流程

Novu Framework Controls:用Schema让非技术人员修改工作流内容

【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu

如果你的工作流用 Novu Framework 写成代码,那么邮件主题、正文、按钮这些内容目前都锁在代码里:运营或设计每次改文案都要找开发。Novu Framework 的 Controls 机制解决这个问题:开发者在步骤上声明一个controlSchema(Zod 或 JSON Schema),Novu Dashboard 会据此自动生成表单,非技术人员在 UI 里修改这些值,平台在运行时对提交的内容做 Schema 校验。本文的任务就是给一个已有的 Framework 工作流加上一组受控的、可被非开发者编辑的内容字段,并在本地预览和验证它们。适用前提是代码优先(code-first)的工作流,即通过@novu/framework定义、通过 Bridge Endpoint 暴露给 Novu Worker Engine 的工作流。

Control Schema 与 Payload Schema 的分工

写代码前先分清两个 Schema 的归属,它们面向不同的人(见 docs/framework/controls.mdx):

  • Control Schema:面向非技术人员和开发者。在 Novu Dashboard UI 中管理,由开发者定义、非技术人员填写。
  • Payload Schema:面向开发者。在novu.trigger时传入(参见 docs/framework/payload.mdx),由开发者自己控制。

文档给出的常见 Controls 用例包括:Content(改邮件主题、正文、推送标题等静态内容)、Styling(按钮颜色、背景色、字号)、Behaviour(显示/隐藏某个区块或按钮)、Order(区块顺序)、Actions(如 digest 时长),以及任何不需要改代码就能调整的场景。

准备工作

以下配置来自 Express 快速上手文档 docs/framework/quickstart/express.mdx,如果你的项目用的是其他框架,serve函数的写法参见 docs/framework/endpoint.mdx 中列出的各框架支持列表。

  1. 安装依赖:
npm install @novu/framework npm install zod

注意 Novu 目前支持的是Zod v3(docs/framework/schema/zod.mdx)。

  1. 在应用中挂载 Bridge Endpoint,让 Novu 能回调你的工作流定义:
app.use(express.json()); // Required for Novu POST requests app.use("/api/novu", serve({ workflows: [testWorkflow] }));
  1. 配置密钥:.env中加入NOVU_SECRET_KEY=your_secret_key,其中your_secret_key换成你自己的 Novu secret key。

  2. 启动应用后运行本地开发命令,它会创建一条隧道并把 Dashboard 打开到Local环境:

npx novu@latest dev

如果你的服务不在默认端口 4000 上,用--port指定,例如npx novu@latest dev --port 3002--route用于修改serve挂载路径(默认/api/novu)。完整的 CLI 参数表见 docs/framework/studio.mdx。

给步骤声明 controlSchema

Controls 挂在具体的步骤上:在step.email等方法的第三个参数里传controlSchema。如果不提供 Schema,TypeScript 会把controls推断为unknown,这是在提醒你显式声明(来源:docs/framework/controls.mdx)。

下面这条 Zod 写法是文档的主路径示例,定义了一个邮件步骤,把主题、横幅显隐和一组内容区块暴露给 Dashboard:

import { z } from 'zod'; import { render } from 'react-email'; import { ReactEmailContent } from './ReactEmailContent'; workflow('new-signup', async ({ step, payload }) => { await step.email( 'send-email', async (controls) => { return { subject: controls.subject, body: render( <ReactEmailContent hideBanner={controls.hideBanner} components={controls.components} /> ), }; }, { controlSchema: z.object({ hideBanner: z.boolean().default(false), subject: z.string().default('Hi {{subscriber.firstName | capitalize}}'), components: z.array( z.object({ type: z.enum(['header', 'cta-row', 'footer']), content: z.string(), }) ), }), } ); });

这里controls就是 Dashboard 上非技术人员保存的表单值的运行时结果,步骤函数内部像普通数据一样使用它。邮件步骤的输出要求见 docs/framework/typescript/steps/email.mdx:subjectbody是必填项,body支持纯文本或 HTML。

用 JSON Schema 声明

如果不想引入 Zod,也可以直接传 JSON Schema 对象。as const用于让 TypeScript 知道该类型不会变化,从而对controls做强类型推断;additionalProperties: false用于禁止出现 Schema 之外的属性。

workflow("new-signup", async ({ step, payload }) => { await step.email( "send-email", async (controls) => { return { subject: controls.subject, body: render( <ReactEmailContent hideBanner={controls.hideBanner} components={controls.components} /> ), }; }, { controlSchema: { // Always `object` type: "object", properties: { hideBanner: { type: "boolean", default: false }, subject: { type: "string", default: 'Hi {{subscriber.firstName | capitalize}}' }, }, required: ["hideBanner"], additionalProperties: false, } as const, } ); });

JSON Schema 的完整写法(嵌套数组、$ref复用、anyOf/oneOf、正则校验等示例)见 docs/framework/schema/json-schema.mdx。

另一种可选方案是 Class-Validator 装饰器类(文档中给出了完整示例),但文档明确警告:使用 Class-Transformer 时嵌套 Schema 对象可能存在不一致,建议先阅读 class-validator-jsonschema 的转换指南再使用。

三种方式的共同点是:所有 Zod 和 Class-Validator Schema 最终都会被编译成 JSON Schema 传给 Novu 平台,平台统一用 JSON Schema 校验 Payload 和 Control 数据。此外,如果只需要本地 IDE 的智能提示、不需要平台侧校验,也可以直接传普通 JS 类,但那不会生成平台可用的 Schema 定义。

Dashboard 表单是如何生成的

定义了controlSchema之后,Novu 会自动在 workflow editor 里生成对应的 Control 表单(docs/framework/schema/zod.mdx)。以 Zod 为例,表单各部分的来源是:

  • Form Input Title:取 Zod Schema 的 key 名。Zod 目前不支持自定义 title。
  • Form Input Type:由 Zod 类型推导,支持stringnumberbooleanenumarray
  • Default Value:取 Schema 的默认值,即z.string().default(...)这类写法。
  • Validation:取 Schema 的校验规则,如minmaxemailurlregex等。

这意味着你在 Schema 里写的类型和约束就是非技术人员在 UI 里能改的范围——超出类型或校验规则的值会被运行时校验拦截,这正是"开发者和非技术同事说同一种语言"的机制所在。

在控制值里使用变量

控制值支持{{variableName}}变量语法,无论这个值是开发者在代码里设置的默认值,还是非技术人员在 Dashboard 里改的。例如{{subscriber.firstName | capitalize}}会在运行时替换为该订阅者的名字。Dashboard UI 提供变量自动补全:输入{{就能看到全部可用变量。可用的变量来源有三类(docs/framework/controls.mdx):

  • Subscriber Attributes:如{{subscriber.firstName}}
  • Payload VariablespayloadSchema中定义的所有 payload 字段,如{{payload.userId}}
  • Liquid Filters:对变量值做格式化,如{{payload.invoiceDate | date: '%a, %b %d, %y'}}会按文档示例格式化为Thu, Jan 01, 24

在本地预览和验证

验证路径分两步,都在 Local 环境完成(docs/framework/studio.mdx):

  1. 运行npx novu@latest dev并保证应用已在运行。Local 环境会实时列出从你的 Bridge Endpoint 发现的所有工作流;命令启动时会打印 Tunnel 地址,例如https://your-tunnel.novu.co/api/novu,这是一个文档示例,你的实际输出以终端为准。
  2. 在 Local 环境的 workflow editor 里打开你声明了controlSchema的步骤,直接修改 Step Controls 表单(改主题、切布尔开关、增删数组项)来预览工作流的不同状态。这一步专门用于调试缺失常量、复杂内容结构等场景。

需要注意:这些表单编辑只存在于本地会话,不会持久化到 Novu Cloud。Local 环境是虚拟的、绑定到你浏览器会话的,只展示在你这台机器上运行的工作流,也不是团队共享环境。

随后触发一次工作流确认端到端流程。从应用侧触发时把bridgeUrl指向你终端打印的 Tunnel 地址,例如(cURL 示例,workflow_identifier换成你的工作流标识,subscriber-id换成目标订阅者,YOUR_API_KEY换成你的 Novu API key):

curl -X POST https://api.novu.co/v1/events/trigger \ -H "Authorization: ApiKey YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "workflow_identifier", "to": { "subscriberId": "subscriber-id" }, "payload": {}, "bridgeUrl": "'"$NOVU_BRIDGE_URL"'" }'

也可以直接通过 Dashboard 的 Local 环境触发。成功的判断依据是 Express 快速上手文档给出的观察点:在 Local 环境中能看到该通知被处理(notification being processed)

同步到 Development / Production

Local 环境没有 Publish 流程,它只反映本机正在运行的代码。要让 Development 或 Production 环境拿到带 Controls 的工作流,需要部署你的 Bridge 应用,并对已部署的服务器(而不是本地隧道)执行 sync(docs/framework/studio.mdx):

npx novu@latest sync \ --bridge-url <YOUR_DEPLOYED_URL_WITH_BRIDGE_ENDPOINT> \ --secret-key <NOVU_SECRET_KEY> \ --api-url https://api.novu.co

其中<YOUR_DEPLOYED_URL_WITH_BRIDGE_ENDPOINT>是部署后应用的 Bridge Endpoint 完整地址(如https://your-app.com/api/novu),<NOVU_SECRET_KEY>是 Novu secret key。Novu Framework 遵循 GitOps 模型:工作流的 source of truth 是 Git 仓库里的代码,官方建议把 sync 命令放进 CI/CD,在每次部署后执行。临时实验也可以把 sync 指向本地隧道 URL,但持久推送到 Development/Production 的正路是部署后同步。

限制与边界

  • bridgeUrl必须是公网可达的地址(CLI 隧道满足要求),私网和localhost地址出于安全原因会被拒绝;Bridge Endpoint 路径不限于/api/novu,但 bridge url 中的路径必须与serve实际挂载路径一致(docs/framework/endpoint.mdx)。
  • Bridge 步骤请求有 5 秒超时;瞬时失败会按指数退避重试最多 3 次(1s、2s、4s),只对408429500503504521522524等状态码和特定网络错误码重试,其他4xx不重试。
  • Zod 无法自定义表单标题,只能以 key 名作为输入框标题;如果需要更友好的展示名,可以考虑 JSON Schema 的title字段(见 docs/framework/schema/json-schema.mdx 示例)。
  • 使用 Class-Validator 时嵌套对象可能有转换不一致,使用前先核对 class-validator-jsonschema 的转换规则。

完成本地验证与 sync 之后,非技术人员即可在对应环境的 Dashboard 中直接维护这些内容字段,而开发者只需要在改 Schema 时承担代码变更。

【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询