
Novu JavaScript SDK 接入指南用 novu/js 构建自定义 In-App 通知收件箱【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu本篇技术指南聚焦于 Novu 开源仓库中的novu/js包packages/js/README.md它是一套面向浏览器的 JavaScript SDK提供与 Novu 平台 In-App 通知交互的低层 API用于构建完全自定义的收件箱Inbox通知体验。读完本文你将掌握 SDK 的安装与初始化、HMAC 加密鉴权含 Subscriber 与 Context 双重哈希、以及 WebSocket 连接的自定义配置并理解其在源码层面的模块划分与实现原理。概览novu/js 是什么novu/js是 Novu 官方发布的 JavaScript SDK包名为novu/js其定位是low-level API——即不预设 UI 形态的底层接口开发者可以在此基础上自由构建适合自身产品风格的收件箱组件。与之相对仓库中还包含开箱即用的 UI 层packages/js/src/ui与主题系统packages/js/src/ui/themes可通过子路径novu/js/ui、novu/js/themes引入。从包清单 packages/js/package.json 可以看到该包同时发布 ESMdist/esm/index.mjs与 CJSdist/cjs/index.js两种产物并额外导出./ui、./themes、./internal三个子路径支持 Tree-ShakingsideEffects: false适合在现代前端构建工具中使用。安装在你的应用中安装 npm 包npm install novu/jsSDK 本身依赖socket.io-client与partysocket详见 packages/js/package.json这两个依赖会在初始化 WebSocket 连接时按需使用无需手动安装。快速开始初始化与获取通知在应用中引入Novu类并传入applicationIdentifier与订阅者标识import { Novu } from novu/js; const novu new Novu({ applicationIdentifier: YOUR_NOVU_APPLICATION_IDENTIFIER, subscriber: YOUR_INTERNAL_SUBSCRIBER_ID, }); const { data: notifications, error } await novu.notifications.list();InfoapplicationIdentifier应用标识符可以在 Novu 控制台的 API Keys 页面找到。这段代码背后发生的关键链路见 packages/js/src/novu.ts构造函数创建HttpClient默认使用apiUrl向后兼容backendUrl与InboxService将subscriber字符串或Subscriber对象规范化为订阅者结构创建Session并立即调用session.initialize()——这一步会携带applicationIdentifier、subscriberHash、contextHash等信息向服务端请求会话令牌token依次挂载notifications、preferences、subscriptions、channelConnections、channelEndpoints五大业务模块调用createSocket建立 WebSocket 连接默认惰性连接仅在订阅 socket 事件时触发connect()。novu.notifications.list()返回统一的结果结构{ data, error }定义见 packages/js/src/types.ts而非抛异常这使错误处理更显式。在 packages/js/src/notifications/notifications.ts 中可以看到list默认limit 10并支持通过useCache开启缓存默认跟随实例级选项useCache ?? true。实例配置参数NovuOptionsNovuOptions的完整定义位于 packages/js/src/types.ts下表汇总了核心参数参数类型说明applicationIdentifierstring必填Novu 控制台 API Keys 页获取subscriberstring \| Subscriber订阅者 ID 或完整订阅者对象推荐subscriberIdstring已废弃的旧写法等价于subscriber传字符串subscriberHashstring开启 HMAC 加密时的订阅者哈希见下文contextContext附加上下文数据如{ tenant, app }contextHashstring开启 HMAC 且使用context时的上下文哈希apiUrlstring自定义 API 地址自托管场景backendUrlstring已废弃改用apiUrlsocketUrlstring自定义 WebSocket 地址socketOptionsNovuSocketOptions自定义 socket 配置见下文useCacheboolean是否启用列表/偏好缓存默认truedefaultScheduleDefaultSchedule默认通知时段调度按周/按天subscriber同时支持完整的Subscriber对象含firstName、lastName、email、phone、avatar、locale、timezone、data等字段见 packages/js/src/types.ts。会话初始化时SDK 会自动补充浏览器时区Intl.DateTimeFormat().resolvedOptions().timeZone见 packages/js/src/session/session.ts。HMAC 加密保护请求与订阅者身份当你在 Novu 环境中启用了 HMAC 加密时必须提供subscriberHash并在使用context时提供contextHash以保护请求安全、防止身份伪造。哈希需要在你自己的后端生成绝不能在前端使用 API Key 计算。Subscriber HMAC在后端使用 Node.js 内置crypto模块生成订阅者哈希import { createHmac } from crypto; const subscriberHash createHmac(sha256, process.env.NOVU_API_KEY) .update(subscriberId) .digest(hex);将其传入 Novu 实例const novu new Novu({ applicationIdentifier: YOUR_NOVU_APPLICATION_IDENTIFIER, subscriber: SUBSCRIBER_ID, subscriberHash: SUBSCRIBER_HASH_VALUE, });Context HMAC可选如果你通过context选项传递附加数据例如租户信息、应用标识同样需要基于规范化后的 context 生成哈希。上下文在序列化前必须经过规范化处理以保证键值顺序不影响哈希结果——README 中使用tufjs/canonical-json的canonicalize函数import { createHmac } from crypto; import { canonicalize } from tufjs/canonical-json; const context { tenant: acme, app: dashboard }; const contextHash createHmac(sha256, process.env.NOVU_API_KEY) .update(canonicalize(context)) .digest(hex);将context与contextHash一并传入const novu new Novu({ applicationIdentifier: YOUR_NOVU_APPLICATION_IDENTIFIER, subscriber: SUBSCRIBER_ID, subscriberHash: SUBSCRIBER_HASH_VALUE, context: { tenant: acme, app: dashboard }, contextHash: CONTEXT_HASH_VALUE, });Note当 HMAC 加密开启且提供了context时contextHash是必填的。哈希与顺序无关{a:1, b:2}与{b:2, a:1}会生成相同哈希。在源码层面subscriberHash与contextHash会在 packages/js/src/session/session.ts 中被原样透传给initializeSession请求由服务端校验签名。Context的类型定义支持标量值与嵌套对象{ id, data }结构见 packages/js/src/types.ts。Socket 选项控制 WebSocket 连接行为你可以通过socketOptions参数提供自定义的 socket 配置这些选项会与默认配置合并后用于初始化 WebSocket 连接。指定 Socket 类型socketType默认情况下SDK 会根据socketUrl自动判断底层实现cloud—— 使用 PartySocketNovu Cloud URL 的默认实现self-hosted—— 使用 socket.io自定义/自托管 URL 的默认实现自动判断的逻辑实现在 packages/js/src/ws/socket-factory.ts当未显式指定socketType时wss://socket.novu.co、wss://eu.socket.novu.co、wss://socket.novu-staging.co等已知 Cloud 地址以及本地开发地址会走 PartySocket其余地址走 socket.io。显式指定类型在通过自有域名代理 Novu Cloud这类场景下非常有用——此时 URL 不再匹配已知的 Novu Cloud 地址但仍需要 PartySocket 行为反过来也可能需要在自定义 URL 上强制 socket.io 行为const novu new Novu({ applicationIdentifier: YOUR_NOVU_APPLICATION_IDENTIFIER, subscriber: YOUR_INTERNAL_SUBSCRIBER_ID, socketUrl: wss://your-proxy.example.com/novu-socket, socketOptions: { socketType: cloud, }, });此外URL 变换映射见 packages/js/src/ws/socket-factory.ts会将https://ws.novu.co等地址自动转换为对应的wss://端点未匹配的地址原样使用。自定义 socket.io 选项当使用 socket.iosocketType: self-hosted或非 Cloud URL时可以透传任意 socket.io-client 选项const novu new Novu({ applicationIdentifier: YOUR_NOVU_APPLICATION_IDENTIFIER, subscriber: YOUR_INTERNAL_SUBSCRIBER_ID, socketOptions: { reconnectionDelay: 5000, timeout: 20000, path: /my-custom-path, // ... 其他 socket.io-client 选项 }, });socket.io 实现的底层细节见 packages/js/src/ws/socket.tsSDK 以io(socketUrl, options)建立连接默认配置reconnectionDelayMax: 10000且仅使用transports: [websocket]并自动携带会话 token 作为 query 参数你传入的socketOptions会通过展开运算符与默认配置合并并覆盖同名项。而对于 PartySocket 实现packages/js/src/ws/party-socket.tstoken 以 URL 查询参数形式附加且默认开启 25 秒间隔的休眠心跳ping消息以保持 Cloud Worker 连接活跃socketOptions中的其余选项会应用于 WebSocket 实例。事件模型与实时能力SDK 内置了事件发射器NovuEventEmitter用于将实时消息分发给业务代码。WebSocket 事件类型定义于 packages/js/src/types.ts事件触发时机notification_received收到新通知unread_count_changed未读数变化unseen_count_changed未读数seen变化agent_eventAgent 相关事件Web Chatsocket 实现会把服务端消息解析后通过novu.on(...)暴露给调用方例如notifications.notification_received、notifications.unread_count_changed、notifications.unseen_count_changed与web_chat.agent_event见 packages/js/src/ws/socket.ts。on方法返回一个清理函数用于取消订阅同时会自动触发 socket 连接见 packages/js/src/novu.ts无需手动调用connect()。更进一步SDK 的模块全景Novu实例挂载了五个核心模块均继承自BaseModule定义见 packages/js/src/base-module.tsnovu.notifications—— 通知的列表、计数、已读/未读、已见/未见、归档、删除、稍后提醒snooze、操作按钮完成/回退等packages/js/src/notifications/notifications.tsnovu.preferences—— 全局与模板级偏好、时段调度packages/js/src/preferencesnovu.subscriptions—— 工作流订阅及订阅级偏好packages/js/src/subscriptionsnovu.channelConnections/novu.channelEndpoints—— 渠道连接与端点管理packages/js/src/channel-connections。此外从包入口 packages/js/src/index.ts 可以看到 SDK 还导出了loadWebChat函数与WebChat相关类型——Web Chat 模块采用按需动态加载novu.loadWebChat()不调用该方法的应用不会下载 Web Chat 代码包这有助于控制初始包体积见 packages/js/src/novu.ts。小结novu/js以轻量、低层的 API 设计覆盖了 In-App 通知的完整生命周期从Novu实例初始化、会话令牌获取到通知列表与状态操作、偏好管理再到基于 HMAC 的双重哈希鉴权和可插拔的 WebSocket 连接层Cloud 走 PartySocket、自托管走 socket.io。理解了本文介绍的NovuOptions各参数与 socket 类型选择逻辑你就能在自有域名代理、自托管部署等复杂场景下正确配置 SDK构建出贴合产品体验的自定义收件箱。【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考