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

kl-boss-message-hub

v1.0.0

Published

跨域跨标签页纯前端消息与会话状态中间件

Readme

kl-boss-message-hub

纯前端跨域、跨标签页消息与会话状态中间件。通过可配置的静态 Hub 页(隐藏 iframe)+ SDK,在同一 hubUrl + namespace 下完成事件在线投递与会话内状态同步。不依赖业务后端、SSE、WebSocket。

从 boss-message-hub 迁移(BREAKING)

| 项目 | 旧 | 新 | |------|----|----| | npm 包名 | boss-message-hub | kl-boss-message-hub | | CDN ESM | boss-message-hub.esm.js | kl-boss-message-hub.esm.js | | CDN IIFE | boss-message-hub.global.js | kl-boss-message-hub.global.js | | 全局对象 | BossMessageHub | 不变(仍为 BossMessageHub) |

pnpm remove boss-message-hub
pnpm add kl-boss-message-hub
# 并将源码中 import 路径改为 'kl-boss-message-hub'

线协议通道名未改,已部署的 Hub 页与新旧 SDK 在协议层仍可互通。

安装与接入

1)<script> 引入(IIFE 全局)

部署 dist/kl-boss-message-hub.global.js 后:

<script src="https://your-cdn/kl-boss-message-hub.global.js"></script>
<script>
  const hub = BossMessageHub.createHub({
    hubUrl: 'https://your-hub-host/hub.html',
    namespace: 'boss',
    onError(err) {
      console.error(err.code, err.message)
    },
  })

  await hub.ready
  hub.subscribe('ui:ping', (payload) => console.log(payload))
  await hub.publish('ui:ping', { from: 'a' })
  await hub.setState('tenant', { id: '1' })
  console.log(await hub.getState('tenant'))
</script>

2)<script type="module"> 引入(ESM)

部署 dist/kl-boss-message-hub.esm.js 后,可用原生 ES Module(相对路径或 CDN URL):

<script type="module">
  import { createHub } from './kl-boss-message-hub.esm.js'
  // 或:import { createHub } from 'https://your-cdn/kl-boss-message-hub.esm.js'

  const hub = createHub({
    hubUrl: 'https://your-hub-host/hub.html',
    namespace: 'boss',
    onError(err) {
      console.error(err.code, err.message)
    },
  })

  await hub.ready
  hub.subscribe('ui:ping', (payload) => console.log(payload))
  await hub.publish('ui:ping', { from: 'a' })
</script>

3)npm / 打包器 ESM

pnpm add kl-boss-message-hub
import { createHub } from 'kl-boss-message-hub'

const hub = createHub({
  hubUrl: 'https://your-hub-host/hub.html',
  namespace: 'boss',
})

4)在 Vue 3 中使用

pnpm add kl-boss-message-hub
<script setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { createHub } from 'kl-boss-message-hub'

const tenant = ref(null)
const lastPing = ref(null)

let hub
let unsubPing
let unwatchTenant

onMounted(async () => {
  hub = createHub({
    hubUrl: 'https://your-hub-host/hub.html',
    namespace: 'boss',
    onError(err) {
      console.error(err.code, err.message)
    },
  })
  await hub.ready

  unsubPing = hub.subscribe('ui:ping', (payload) => {
    lastPing.value = payload
  })
  unwatchTenant = hub.watchState('tenant', (value) => {
    tenant.value = value
  })
})

async function sendPing() {
  await hub?.publish('ui:ping', { from: 'vue3' })
}

async function saveTenant() {
  await hub?.setState('tenant', { id: '1' })
}

onUnmounted(() => {
  unsubPing?.()
  unwatchTenant?.()
  hub?.destroy()
})
</script>

<template>
  <div>
    <p>tenant: {{ tenant }}</p>
    <p>lastPing: {{ lastPing }}</p>
    <button type="button" @click="sendPing">publish</button>
    <button type="button" @click="saveTenant">setState</button>
  </div>
</template>

5)在 Vue 2 中使用

npm install kl-boss-message-hub
# 或 yarn add kl-boss-message-hub

Vue 2 + webpack/vue-cli 一般可直接 ESM 引入;若构建报错,确认 babel 能转译 node_modules/kl-boss-message-hub(按需加入 transpileDependencies)。

<template>
  <div>
    <p>tenant: {{ tenant }}</p>
    <p>lastPing: {{ lastPing }}</p>
    <button type="button" @click="sendPing">publish</button>
    <button type="button" @click="saveTenant">setState</button>
  </div>
</template>

<script>
import { createHub } from 'kl-boss-message-hub'

export default {
  name: 'HubDemo',
  data() {
    return {
      tenant: null,
      lastPing: null,
      hub: null,
      unsubPing: null,
      unwatchTenant: null,
    }
  },
  async created() {
    this.hub = createHub({
      hubUrl: 'https://your-hub-host/hub.html',
      namespace: 'boss',
      onError(err) {
        console.error(err.code, err.message)
      },
    })
    await this.hub.ready

    this.unsubPing = this.hub.subscribe('ui:ping', (payload) => {
      this.lastPing = payload
    })
    this.unwatchTenant = this.hub.watchState('tenant', (value) => {
      this.tenant = value
    })
  },
  methods: {
    async sendPing() {
      await this.hub.publish('ui:ping', { from: 'vue2' })
    },
    async saveTenant() {
      await this.hub.setState('tenant', { id: '1' })
    },
  },
  beforeDestroy() {
    if (this.unsubPing) this.unsubPing()
    if (this.unwatchTenant) this.unwatchTenant()
    if (this.hub) this.hub.destroy()
  },
}
</script>

Vue 2.7 若用 Composition API,写法可对齐 Vue 3;销毁钩子用 onBeforeUnmount(不要用已废弃的 beforeDestroy 选项混用同一实例)。

部署 Hub

pnpm builddist/ 产物分工如下:

| 文件 | 用途 | 是否进 npm | |------|------|------------| | index.js + index.d.ts | npm / 打包器 import { createHub } from 'kl-boss-message-hub' | 是 | | kl-boss-message-hub.esm.js | <script type="module"> / CDN 直链 | 否(静态资源) | | kl-boss-message-hub.global.js | <script> 全局 BossMessageHub | 否(静态资源) | | hub.html + hub.js | Hub 中继页(hubUrl 指向 hub.html) | 否(运维部署) |

pnpm build
# npm 发布:见下方「发布到 npm」
# Hub / CDN:把对应 dist 文件拷到静态服务器或对象存储

要点:

  • hubUrlnamespace 均必填,无默认值
  • 要互通的子系统必须配置完全相同hubUrl + namespace
  • Hub 部署域不写死;换环境换 hubUrl 即可隔离

发布到 npm

一键脚本会校验包名、Git 干净工作区、npm 登录,再执行 build / test / pack 内容检查,通过后才 pnpm publishnpm 包仅含 SDKdist/index.js + dist/index.d.ts);hub.html / hub.js 与 CDN 文件不会进包,需按上一节单独部署。

发版前请先手动改好 package.jsonversion(脚本不自动 bump)。

# 建议先 dry-run(构建 + 校验,不上传)
pnpm release -- --dry-run

# 交互确认后发布
pnpm release

# 跳过确认(CI / 明确发版时)
pnpm release -- --yes

常用参数:

| 参数 | 含义 | |------|------| | --dry-run | 跑完检查与 pack 校验,不上传 | | --yes | 跳过「确认发布」提示 | | --skip-tests | 跳过 pnpm test(不推荐) | | --allow-dirty | 允许未提交变更时发布(不推荐) |

常见失败:未 npm login、工作区有未提交改动、目标 version 已在 registry 存在。

API 概要

| API | 说明 | |-----|------| | publish / subscribe | 事件通道:在线投递,不持久、不重放 | | setState / getState / watchState / deleteState | 状态通道:逻辑会话内持久;watchState 含首包快照 | | probe() | 连通探测(加载 / 握手 / 跨 Tab) | | destroy() | 销毁 iframe 与监听 |

状态仅在逻辑会话内有效(有存活参与者)。全部 Tab 离开或冷启动发现无存活 peer 时会清空该 namespace 会话态。

默认可信 Origin

默认信任:

  • *.kailinjt.com
  • *.kailinesb.com
  • localhost / 127.0.0.1 / [::1](任意端口,http/https)

trustedOrigins 追加到默认列表,不替换。hubUrl 自身 Origin 始终可信。

错误码(节选)

INVALID_CONFIGHUB_LOAD_TIMEOUTHUB_HANDSHAKE_FAILEDORIGIN_REJECTEDCROSS_TAB_UNREACHABLESTORAGE_PARTITIONEDPAYLOAD_NOT_SERIALIZABLESTORAGE_QUOTA_EXCEEDEDHUB_VERSION_MISMATCH

通过 onError 与 Promise 拒绝暴露,避免静默失败。

安全注意

  • 白名单内脚本均可读写总线,视为半公开通道,不要传递长期凭证
  • Payload 须 JSON 可序列化;不设单条字节上限,但存储配额耗尽会报错
  • 跨站嵌入 Hub 可能受浏览器存储分区影响,请用 probe() 确认跨 Tab 可用;建议 Hub 与多数业务同站部署

非目标

跨设备同步、跨会话永久状态、业务后端通道、双 hubUrl 自动桥接、首版 RPC。

开发与验证

要求 Node.js ^24。

pnpm install
pnpm test          # 纯函数单测 + 协议集成测(happy-dom)
pnpm build
pnpm dev           # 双 port 真跨 Origin Playground
pnpm test:e2e      # 本地 Playwright(不接 CI)

Playground 端口(真跨 Origin)

| 地址 | 角色 | |------|------| | http://127.0.0.1:5173/?app=a | 子系统 A | | http://127.0.0.1:5174/?app=b | 子系统 B(不同 port → 不同 Origin,同主机 → 同站) | | http://127.0.0.1:5175/hub.html | Hub(默认 hubUrl) |

说明:若用 localhost127.0.0.1 混搭,Hub 对其中一方是跨站第三方,易触发存储分区导致跨 Tab 不通;Playground 故意用同主机双 port 验证「真跨 Origin」且通道可用。

面板支持连接 / 事件 / 状态 / probe / destroy,以及故障注入(错误 hubUrl、不可序列化载荷、destroy 后调用)。

E2E

首次安装浏览器(走 npmmirror,仅 chromium,比官方源快):

pnpm playwright:install
# 等价于:
# PLAYWRIGHT_DOWNLOAD_HOST=https://cdn.npmmirror.com/binaries/playwright pnpm exec playwright install chromium

pnpm test:e2e

test:e2e 会通过 Playwright webServer 拉起 pnpm dev(若端口已被占用且非 CI,可复用已有服务)。本仓库不将 E2E 作为 CI 门禁。

若镜像仍慢,可自设镜像:

PLAYWRIGHT_DOWNLOAD_HOST=https://your-mirror pnpm playwright:install