npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nexusmc-cn/nexuspulse

v0.1.3

Published

TypeScript browser notification runtime for Push, Notifications, Service Workers, WebSocket and Badging

Readme

NexusPulse

NexusPulse 是一个浏览器端 TypeScript 通知运行时,将 Notifications API、Push API、Service Worker、WebSocket 和 Badging API 统一到一个生命周期中。

npm 包页面 · 配套服务端包

安装

npm install @nexusmc-cn/nexuspulse

原无 scope 包 nexuspulse 的使用方需要将依赖名称和模块导入改为 @nexusmc-cn/nexuspulse;Service Worker 文件名和通知点击消息类型保持不变。

包提供三个入口:

  • @nexusmc-cn/nexuspulse:应用窗口中的 NexusPulse 运行时和各个适配器。
  • @nexusmc-cn/nexuspulse/service-worker:在 Service Worker 文件中安装 Push 和通知点击处理器。
  • @nexusmc-cn/nexuspulse/protocol:浏览器与服务端共享的 NotificationPayload 和 NotificationAction 协议类型。

最小接入

import { createNexusPulse } from "@nexusmc-cn/nexuspulse";

const pulse = createNexusPulse({
  serviceWorker: { url: "/nexuspulse-sw.js" },
  push: { applicationServerKey: vapidPublicKey },
  webSocket: {
    url: "wss://example.test/notifications",
    reconnect: { maxAttempts: 5 },
  },
});

await pulse.initialize();
await pulse.requestPermission();

pulse.on("notification", (payload) => {
  console.log("通知已展示", payload.id);
});

await pulse.notify({
  title: "构建完成",
  body: "你的构建已经可以下载。",
  url: "/builds/latest",
});

createNexusPulse() 和导入包本身不会访问浏览器全局对象。将初始化放在浏览器生命周期中调用;initialize() 会按配置注册 Service Worker 并把状态变为 ready。调用 dispose() 会断开 WebSocket、释放订阅状态并移除事件监听器。

Service Worker

在应用自己的构建流程中创建 Service Worker 文件:

// src/nexuspulse-sw.ts
import { installNexusPulseServiceWorker } from "@nexusmc-cn/nexuspulse/service-worker";

installNexusPulseServiceWorker();

将产物部署到与页面同源的 /nexuspulse-sw.js,然后把相同路径传给 serviceWorker.url。Push 数据应为 JSON 格式的 NotificationPayload,例如:

@nexusmc-cn/nexuspulse/protocol 仅导出类型,没有运行时值;请使用类型导入。服务端包复用这组协议类型,避免两端维护不同定义。

import type {
  NotificationAction,
  NotificationPayload,
} from "@nexusmc-cn/nexuspulse/protocol";
{
  "title": "构建完成",
  "body": "点击查看构建结果",
  "url": "/builds/latest",
  "data": { "buildId": "build-123" }
}

Push 通知点击时,如果 Service Worker 能枚举到已打开的目标页面,NexusPulse 会聚焦该窗口并发送 nexuspulse:notification-click 消息;否则直接打开 url,并向新窗口尝试发送点击消息。跨源页面即使已打开也不会被 clients.matchAll() 枚举到。页面应根据 URL 加载内容,不依赖点击消息一定送达。没有 url 时会聚焦已有同源窗口。默认只允许当前页面同源地址。如确实需要跳转到其他源,应在 Service Worker 安装器中显式配置 allowedOrigins,并在服务端限制可发送的 URL。

installNexusPulseServiceWorker({
  allowedOrigins: ["https://app.example.test"],
});

Push 和 VAPID

await pulse.requestPermission();
const subscription = await pulse.subscribePush();

// 将 subscription.toJSON() 发送到你自己的后端保存。
console.log(subscription.toJSON());

applicationServerKey 是服务端 VAPID 公钥,可以传 BufferSource 或字符串。NexusPulse 不保存 VAPID 私钥,也不定义服务端推送协议;服务端应自行保存订阅信息并使用 Web Push 服务发送消息。取消订阅:

await pulse.unsubscribePush();

订阅前需要已注册的 Service Worker、通知权限和浏览器 Push API。没有配置 serviceWorker.url 或已有 registration 时,subscribePush() 会抛出 InvalidConfigurationError。

WebSocket

WebSocket 消息默认按 JSON 解码为 NotificationPayload,并保留 data 和顶层 url:

const pulse = createNexusPulse({
  webSocket: {
    url: "wss://example.test/notifications",
    reconnect: {
      maxAttempts: 3,
      initialDelay: 250,
      maxDelay: 10_000,
      factor: 2,
    },
  },
});

await pulse.connect();
pulse.on("message", (payload) => {
  console.log("收到消息", payload.title);
});

pulse.disconnect();

服务端消息格式不同时可配置 decodeMessage;转换时需保留 data 和顶层 url,否则文件 ID、上传 ID 和点击链接会丢失。

默认情况下,WebSocket 收到消息后会先触发 message,再展示前台系统通知并触发 notification。如果只需要处理站内消息,可设置 webSocket.autoNotify: false;此时仍触发 message,但不会自动展示系统通知。显式调用 pulse.notify() 和 Push 通知不受此开关影响。

const pulse = createNexusPulse({
  webSocket: {
    url: "wss://example.test/notifications",
    autoNotify: false,
  },
});

自动展示的通知会把顶层 url 写入 data.url,点击时由当前页面打开该地址;默认只允许同源 URL。跨源文件详情页还需在窗口端配置 security.allowedOrigins,并为 Push 点击单独配置上文的 Service Worker allowedOrigins。顶层 allowedOrigins 是窗口端的兼容别名;两者同时配置时,security.allowedOrigins 优先,包括设为空数组的情况。成功通知的文件 ID 应放在 data.fileId;失败时尚无文件 ID,可用 data.uploadId 和失败详情页 url。通知 id 不代替文件 ID 或上传 ID。

const pulse = createNexusPulse({
  security: { allowedOrigins: ["https://files.example.test"] },
  webSocket: { url: "wss://example.test/notifications" },
});

默认不自动重连。配置 reconnect 后使用指数退避,达到 maxAttempts 会发出 error 事件并停止连接。connect() 只会在连接成功后 resolve;初始连接失败、连接在打开前关闭或主动断开时会 reject ConnectionError。

Badging API

await pulse.setBadge(3);
await pulse.clearBadge();

setBadge() 和 clearBadge() 返回 Promise<boolean>。浏览器不支持 Badging API 时返回 false,不会阻断通知流程;也可以用 badge: { enabled: false } 完全关闭徽章调用。

权限、安全与 SSR

  • Notifications、Push 和 Service Worker 通常要求安全上下文(HTTPS 或 localhost),并应在用户手势触发的流程中请求权限。
  • Service Worker 的 URL 和作用域必须与部署位置匹配;页面刷新后可以继续复用已有 registration。
  • NotificationPermission 被拒绝时,权限请求和 Push 订阅会抛出 PermissionDeniedError;能力不存在会抛出 UnsupportedFeatureError。
  • 应用可以通过 on("statechange", ...)、on("permissionchange", ...)、on("subscriptionchange", ...) 和 on("error", ...) 观察运行时状态。
  • SSR 环境可以安全导入和创建实例,但浏览器相关方法应只在客户端调用。

模块格式

三个入口均提供 ESM、CommonJS、source map 和 TypeScript 类型声明,可由应用的构建工具按模块格式解析。

许可

MIT © 2026 NexusMC-CN