Unicall:一个 URL 驱动的轻量通知运行时 SDK

项目地址:https://github.com/noblesnowfield/unicall

文档站:https://noblesnowfield.github.io/unicall-doc/

npm 包:@noblesnowfield/unicall

带有快速本地调试启动的测试页面

导航

为什么做 Unicall

很多项目都会遇到"通知"这个需求:服务异常要发消息,部署完成要提醒,定时任务失败要报警,业务事件要推送到微信、邮箱或 Webhook。

一开始这通常很简单:

ts 复制代码
await fetch('https://example.com/webhook', {
  method: 'POST',
  body: JSON.stringify({ text: '任务完成' })
});

但随着项目变复杂,问题也会变多:

  • 不同通知渠道有不同格式。
  • 有些渠道支持 Markdown,有些只支持纯文本。
  • 邮件要支持 HTML 和附件。
  • Webhook、Pushplus、WxPusher、SMTP 的配置方式各不相同。
  • 失败后要重试,超时要中断,重复消息要去重。
  • 前端不能暴露服务端密钥。

所以我做了 Unicall。

Unicall 是什么

Unicall 是一个面向 Node.js / TypeScript 的轻量通知运行时 SDK。

它的目标不是简单封装某一个 Webhook,而是提供一个统一的通知运行时:

text 复制代码
Message -> Runtime -> Middleware -> Provider -> Target

你可以用一条 Provider URL 描述通知目标,例如:

text 复制代码
webhook://127.0.0.1:4317/mock/webhook?scheme=http&method=POST
pushplus://PUSHPLUS_TOKEN?template=markdown
smtp://user:pass@smtp.example.com:465
wxpusher://APP_TOKEN?uid=USER_UID

然后通过统一 API 发送消息。

核心设计

Unicall 的核心设计有三个关键词。

1. URL-driven

通知目标用 URL 表达,适合配置化管理,也方便在本地、测试、生产环境之间切换。

2. Provider-based

每个通知渠道都是独立 Provider。Runtime 不硬编码任何具体渠道逻辑,新增渠道时只需要实现统一接口。

3. Middleware-first

发送流程天然经过中间件,可以组合:

  • retry
  • timeout
  • logging
  • metrics
  • dedupe
  • rate limit

这让通知能力更像一个小型运行时,而不是一堆零散的工具函数。

快速开始

安装:

bash 复制代码
npm install @noblesnowfield/unicall

发送一条 Webhook 通知:

ts 复制代码
import { createDefaultProviderRegistry, notify } from '@noblesnowfield/unicall';

const results = await notify(
  'webhook://127.0.0.1:4317/mock/webhook?scheme=http&method=POST',
  {
    title: 'Unicall test',
    text: 'Hello from Unicall.'
  },
  {
    registry: createDefaultProviderRegistry()
  }
);

console.log(results[0]?.success);

如果需要复用多个目标,可以使用 NotificationRuntime

ts 复制代码
import {
  NotificationRuntime,
  createDefaultProviderRegistry,
  retryMiddleware,
  timeoutMiddleware
} from '@noblesnowfield/unicall';

const runtime = new NotificationRuntime({
  registry: createDefaultProviderRegistry(),
  middleware: [
    timeoutMiddleware({ timeoutMs: 5000 }),
    retryMiddleware({ retries: 2 })
  ]
});

runtime.add([
  'webhook://127.0.0.1:4317/mock/webhook?scheme=http&method=POST',
  'pushplus://PUSHPLUS_TOKEN?template=markdown'
]);

await runtime.send({
  title: '部署完成',
  markdown: '## Unicall\n\n生产环境部署完成。'
});

Provider 支持

当前已经支持:

Provider 协议 适合场景
Webhook webhook:// 自有服务、本地 mock、后端代理
Email / SMTP smtp://mailto:// HTML 邮件、附件、运维通知
喵提醒 miaotixing:// 个人轻量文本提醒
Pushplus pushplus:// 微信消息、Markdown / HTML 推送
WxPusher wxpusher:// 微信公众号应用推送

Provider 文档可以看这里:

https://noblesnowfield.github.io/unicall-doc/providers/webhook

中间件能力

Unicall 把中间件作为一等能力,而不是事后补丁。

例如:超时 + 重试。

ts 复制代码
const runtime = new NotificationRuntime({
  registry: createDefaultProviderRegistry(),
  middleware: [
    timeoutMiddleware({ timeoutMs: 3000 }),
    retryMiddleware({ retries: 3 })
  ]
});

这类能力在通知场景里很实用:

  • 第三方服务偶发失败,可以重试。
  • 某个渠道响应太慢,可以超时。
  • 重复事件可以去重。
  • 高频通知可以限流。
  • 发送结果可以接入 metrics。

浏览器接入与安全边界

Unicall 也提供浏览器构建:

ts 复制代码
import { NotificationRuntime } from '@noblesnowfield/unicall/browser';

也可以使用 <script>

html 复制代码
<script src="./dist/unicall.global.js"></script>
<script>
  const runtime = new Unicall.NotificationRuntime();
</script>

但需要特别注意:不要在浏览器代码里暴露服务端密钥。

例如这些都不应该放在前端:

  • SMTP 密码
  • Pushplus token
  • WxPusher app token
  • 企业微信 webhook key
  • 飞书 / 钉钉 secret

更推荐的生产链路是:

text 复制代码
Browser -> 你的后端 /api/notify -> Unicall Runtime -> Provider

适合哪些场景

Unicall 比较适合:

  • Node.js 项目通知聚合
  • 定时任务失败告警
  • 部署完成提醒
  • 业务事件推送
  • 内部系统 Webhook 转发
  • 邮件 + 微信类通知统一封装
  • 需要 retry / timeout / dedupe 的通知场景

如果只是一个一次性的 fetch(webhook),可能不需要它。

但如果你开始同时接入多个通知渠道,并且希望配置、消息模型、错误处理和中间件统一,Unicall 会更合适。

后续计划

后续我希望继续完善:

  • 更多国内常用通知 Provider
  • 更完整的 Provider URL 文档
  • 更丰富的模板示例
  • 浏览器端安全接入示例
  • 更完善的 CI 发布和自动化验证

Unicall 目前已经发布到 npm:

bash 复制代码
npm install @noblesnowfield/unicall

完整文档:

https://noblesnowfield.github.io/unicall-doc/

如果你也在项目里维护过一堆零散的通知脚本,Unicall 想解决的正是这个问题:用统一的运行时,把通知能力变成可以组合、可以测试、可以长期维护的基础设施。

相关推荐
SunkingYang5 个月前
使用TortoiseGit工具推送(push)时,忘了先拉取(Pull),提示冲突,后续怎么处理冲突?
git·tortoisegit·pull·push·推送·冲突·拉取
WuWuII7 个月前
SSE服务端单向推送消息到前端
前端·推送
白萝卜弟弟1 年前
【推送】主流的服务端推送技术的对比
后端·推送
SuperHeroWu72 年前
【HarmonyOS】应用推送使用个推SDK如何实现?
华为·harmonyos·鸿蒙·推送·个推
sheng_er_sheng2 年前
【Flutter】极光推送配置流程(小米厂商通道) 章二
flutter·推送
沐雨潇竹2 年前
GitHub无法完成推送 的设置选项
github·copilot·推送
BruceGerGer3 年前
flutter开发实战-实现推送功能Push Notification
android·flutter·ios·推送·notification