# @finueva/pub-sub 中文文档

规范地址：https://npmcn.com/package/%40finueva/pub-sub/

版本：0\.14\.0
npm 元数据更新时间：2026-10-30T09:26:29.316Z
中文译文更新时间：2026-11-14T19:59:57.386Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40finueva/pub-sub
原文对照：https://npmcn.com/package/%40finueva/pub-sub/?lang=original
项目主页：https://github.com/Ifkafin/pub-sub#readme
源码仓库：https://github.com/Ifkafin/pub-sub

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：470 kB，63 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：3 个
- 首次发布：2026-08-19T17:53:12.953Z
- 最新版本发布：2026-10-30T09:26:29.070Z
- 近 30 天下载量：2420（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：16（近 12 个月 16 个）

## 中文简介

Finueva Pub 子网络 SDK

## 安装

```sh
npm install @finueva/pub-sub
```

也可以使用：`pnpm add @finueva/pub-sub`、`yarn add @finueva/pub-sub`、`bun add @finueva/pub-sub`

## README

# `@finueva/pub-sub`

使用 `@finueva/pub-sub` 接收现场活动,管理浏览器推,出票,发布活动.

已确认的Web 连接可选择使用 `connect({ deliveryMode: "acknowledged", reauthorization: true, onEvent })` 在经纪人支持现场更新后。 SDK通过同样方式获得新票 `getTicket` 提供者,请求采取行动 `reauthorize` (签名像 `connect`,并重新授权现有订阅。 申请表必须重新验证每张票申请的会话权限。 成功更新不会释放新的打开状态; 实际失败会关闭套接字, 仍然需要应用程序重新连接/ 抓取 。 在启用此选项之前部署经纪人支助。 默认的边界替换行为和遗产v1不变.

Pub Sub是实验性的. 它试图立即交付。 它不保留、重放、顺序、重试、去重复或确认事件.

## 安装 SDK

```sh
pnpm add @finueva/pub-sub
```

Node.js工具和服务器应用程序需要Node.js 22或更晚.

## 不透明通道信号

下一个小SDK加 `client.createSignalingClient(...)` 到峡谷 `createPubSubClient` 结果。 它为Cloudflare使用相同的配置服务源和WebSocket厂或由明确组成的节点中继器. 信任的服务器客户端 `issueChannelTicket({ userId, channel, publish, subscribe, expiresAt })` 申请授权后提供一次性使用补助金; `expiresAt` 这是一个绝对的毫秒期限,最多提前60秒.

```ts
const signaling = await client.createSignalingClient({
  userId: authorizedOwner,
  channel: authorizedChannel,
  getTicket: (signal) => requestApplicationChannelTicket(signal),
  onPeers: (self, peers) => peerProvider.updatePeers(self, peers),
  onEvent: ({ peerId, payload }) => peerProvider.receive(peerId, payload),
});
signaling.publish(opaquePayload, optionalRecipientPeerId);
await signaling.closed;
```

`userId` 是房间的主人名空间 而不是连接参与者的个人身份 获准使用同一所有者/渠道的参与者获得明确签名 `peerId` 连接身份。 其他拥有相同频道名的所有人被隔离. 目前所有者房容量为4个接通. 数据和同行存在在能力到期时终止;应用程序必须重新授权并重新连接。 Pub Sub不解释有效载荷或执行WebRTC或资源政策.

`connectChannel` 也可从下列网址获得: `@finueva/pub-sub/channels`。对于服务器宣布的替代节点路线,请通过所公布的绝对 `websocketUrl`;它必须共享配置的服务源,并且不包含查询、片段或证书。 服务器验证了票签的准确路径. 两种运行时间都使用通道/ticket子protocols,从未使用过售票查询参数. 见仓库的 [频道架构](https://github.com/Ifkafin/pub-sub/blob/staging/apps/developer/docs/architecture/channel-signaling.md) 用于节点供应商合同和路由构成。 假设服务推出后发布的微量发布;来源可用性并不意味着这些方法存在于安装在更早的SDK中.

## API 摘要

浏览器客户端 :

| 方法 | 说明 |
| --- | --- |
| `connect()` | 打开现场事件连接 . |
| `enablePush()` | 启用当前浏览器安装的推动 . |
| `disablePush()` | 禁用当前浏览器安装的推力 . |
| `onPush()` | 听听推收和通知窃听器. |

服务器客户端 :

| 方法 | 说明 |
| --- | --- |
| `issueTicket()` | 开出一张订户业务的票. A 类 `connect` 罚单可以声明 `capabilities` 例如 `presence.hint.subject.v1`,则a `leaseKey` 用于套接字输入的显示表. |
| `publish()` | 向一个应用程序定义的用户发布事件 . |
| `putInstallation()` | 以可选的重试安全突变字段注册安装 . |
| `observeInstallation()` | 请检查date=中的日期值 (帮助). |
| `deleteInstallation()` | 只删除预期的安装化身. |

## 创建浏览器客户端

提供经认证的用户身份证和 `getTicket` 函数。 该函数必须请求应用程序服务器的出票 .

```ts
import { createPubSubClient } from "@finueva/pub-sub";

const pubSub = await createPubSubClient({
  userId: currentUser.id,
  async getTicket({ action, signal }) {
    const response = await fetch("/api/pub-sub/ticket", {
      method: "POST",
      credentials: "include",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ action }),
      signal,
    });

    if (!response.ok) throw new Error("Pub Sub ticket unavailable");
    return ((await response.json()) as { ticket: string }).ticket;
  },
});
```

您的服务器必须从已认证的会话数据获取用户ID 。 不接受请求机构的用户ID. 从不向浏览器代码发送 Pub Sub API 令牌 .

生产是默认的环境. 没有明确的公开配置,客户端创建会让一个进入 `/v1/configuration` 在嵌入式生产服务来源上,没有饼干或Vault头. 它在3秒和16个KiB内接受一个完整的公用捆绑;重定向,失败,以及无效或部分的回放保留完整的嵌入捆绑而无需重试. 通过 `serviceOrigin`, (中文(简体) ), `variables`,或 `push.firebase` 跳过此请求,并将调用器值合并到选中的嵌入式捆绑上。 过 `environment: "staging"` 以选择中转服务和后退捆绑。 该服务返回其缓存配置快照, 而不是新读的 OpenBao 。 浏览器访问需要服务允许的来源 .

## 接收现场事件

打电话 `connect()` 和处理事件 `onEvent`。 。 。 .

```ts
const connection = await pubSub.connect({
  onEvent(event) {
    if (event.type === "order.updated") {
      refreshOrder(event.data);
    }
  },
});

// Close the connection on sign-out or account change.
connection.close();
await connection.closed;
```

`event.data` 实值 `unknown`在使用前验证。 SDK没有重新连接. 打电话 `connect()` 以创建新的连接。 断开时发送的事件不重放 .

注册的托管应用程序必须设置 `deliveryMode: "acknowledged"` 内 `connect()`此选择 `finueva.pubsub.v2` 而不退为v1. SDK验证了每个被捆绑的帧,在返回匹配的运输信用之前承认它为回调. 一个同步回调失败会关闭连接而无信用. 信用确认运输准入,而非同步持久性或电文读取状态.

主机服务在未完成的框架,字节,附件或最后期限界限被达到后会关闭缓慢的连接. 在重新连接或光标缺口后通过应用程序的 API 恢复当前授权状态 。 不保留活事件体进行运输回放. 独立的遗留应用命名空间保留其单独的现有协议.

## 每个浏览器共享一个连接

与 `connectionSharing`,每个标签的确认 `connect()` 加入浏览器中每个用户一个套接字, 而不是每个选项卡中每个经纪人的8个用户。 这个 `connect()` API和返回的连接不变.

```ts
import PubSubWorker from "@finueva/pub-sub/shared-connection-worker?sharedworker";

const pubSub = await createPubSubClient({
  userId,
  getTicket: async ({ action, signal, leaseKey }) => myTicket({ action, leaseKey }, signal),
  connectionSharing: { sharedWorker: () => new PubSubWorker({ name: "pub-sub" }) },
});
```

-   套接字在一个共享工作人中运行, 当你提供一个, 否则在使用 Web Locks 选择的领袖标签中运行 `BroadcastChannel`。 。 。 . `mode: "leader"` 跳过共享工作者.
-   没有网页锁定和 `BroadcastChannel`,每个标签单独连接,完全一样不共享.
-   每个标签仍然用自己的票来证明自己的会话 `getTicket`。拒绝为另一个用户提供机票,不同的用户从来不共用套接字.
-   每个分页都接收其用户的每个事件. 每分页都会确认一个事件 `onEvent` 已经返回.
-   领头人交接,领头人损失或工人停手 通常每个分页 `closed` 州,所以重新连接 和赶超留在你的.
-   共享连接通行证 `leaseKey` 改为 `getTicket` 联合国 `connect` 门票并曝光为 `connection.leaseKey`把它签入罚单 并用它来做套接字表.

见ADR0006(每个浏览器一个共享用户连接),用于设计及其取舍.

## 启用浏览器推

在控制您的应用程序来源的服务人员中安装收听器.

```ts
import { installPubSubServiceWorker } from "@finueva/pub-sub/service-worker";

installPubSubServiceWorker({
  notificationIcon: "/notification.png",
  openPath: "/inbox",
});
```

打电话 `enablePush()` 在用户动作后,例如点击按钮.

```ts
const stopPushEvents = pubSub.onPush((event) => {
  if (event.kind === "tapped") {
    openEvent(event.eventId, event.eventType);
  }
});

const enabled = await pubSub.enablePush();

// Disable push on opt-out, sign-out, or account change.
await pubSub.disablePush();
await enabled.unlisten();
await stopPushEvents();
```

按下事件包含事件 ID、事件类型、可选显示文本以及可选的 a `tag` 和路线 `data` 您的服务器所附带的条目 。 应用程序打开后从授权的 API 获取当前应用程序数据 .

服务- 员工帮助者也接受 `onPush(metadata)` 显示和返回前运行的钩子 `"default"` 或者说 `"handled"`;扔出或拒绝返回到 `"default"`时 `openPath` 设置,一个水龙头导航一个同一来源的现有窗口。 默认情况下, SDK 将它的安装 ID 和 order 保存在 `localStorage` 在不限制用户范围的密钥下; 通过用户范围 `push.storage` 如果多个用户共享浏览器配置文件.

## 创建服务器客户端

仅从服务器代码导入服务器入口 .

```ts
import { createPubSubServerClient } from "@finueva/pub-sub/server";

const pubSub = createPubSubServerClient({
  apiToken: process.env.PUB_SUB_API_TOKEN!,
});
```

### 开罚单

```ts
const ticket = await pubSub.issueTicket({
  userId: authenticatedUser.id,
  action: "connect",
});
```

### 管理已注册的推力安装

已注册的安装写作可能省略了"一能"字段的相容性;每个这样的写作都是由服务器发行的新安装化身,没有再播放的收取. 移民意识召唤者应坚持UUIDv7 `idempotencyKey`一种新鲜的化身UUID,和 `expiresAt` 在第一次请求之前,再使用 每次重试时, 都会有确切的拖累。 固定的过期时间必须是钥匙嵌入时间戳后七天. 其结果包括不可改变的驱逐对夫妇`installationId` 加号 `incarnation`)和单独重算 `authority` 状况(`owned`, (中文(简体) ), `unowned`,或不透明 `superseded`) (中文(简体) ).

使用 `observeInstallation()` 以在修复或倒置前检查符号所有权。 服务器客户端 `deleteInstallation()` 是有条件的:通过符号和预期的化身;它称为单独的 `/authority` 结束点和返回 `removed`, (中文(简体) ), `absent`,或 `superseded`。浏览器/ Tauri 来宾 `disablePush()` 仍然以罚单为主,在遗留的DELETE路线上没有身体。 即使远程撤销失败,它也会耗尽听众,使本地提供者的代号失效,但拒绝者仍保留远程清理的不确定性。 它拒绝 `PUSH_TOKEN_DELETE_FAILED` 只有在服务回答安装被移除,本地提供者的代号无法被删除后,应用程序才能完成该代码上的选择退出或签名. 任何其他拒绝都未经证实.

### 发布事件

```ts
const result = await pubSub.publish({
  userId: recipient.id,
  event: {
    id: crypto.randomUUID(),
    type: "order.updated",
    occurredAt: new Date().toISOString(),
    data: { orderId: order.id },
    push: {
      title: "Order updated",
      body: "Open the application for details.",
    },
  },
});
```

奥米 `push` 发送此事件只用于实时连接。 将私人信息从推出显示文本中保留,因为操作系统可以在锁屏幕上显示.

## 处理错误

SDK 操作抛出 `PubSubError`。使用它的马厩 `code` 属性来选择重试或用户界面行为.

```ts
import { PubSubError } from "@finueva/pub-sub";

try {
  await pubSub.connect({
    onEvent(event) {
      handleApplicationEvent(event);
    },
  });
} catch (error) {
  if (error instanceof PubSubError && error.code === "OPERATION_TIMED_OUT") {
    showRetryAction();
  }
}
```

出版非一能. 未知结果后的重试可以不止一次地发送同一事件.

## 学多点

-   [网络应用程序](https://pub-sub.finueva.com/guides/web-sdk)
-   [服务器应用程序](https://pub-sub.finueva.com/guides/server-sdk)
-   [交付行为](https://pub-sub.finueva.com/guides/delivery)
-   [警卫](https://pub-sub.finueva.com/guides/security)
-   [服务 API](https://pub-sub.finueva.com/guides/service-api)

## 许可证

麻省理工学院

### 私人手表(未公布候选人)

服务器入口提供 `registerPresenceWatch`, (中文(简体) ), `renewPresenceWatch` 财务报告和审定财务报表 `cancelPresenceWatch`配置已注册 `application` 别名及其别名 `apiToken`生成新手表 UUID v4 并生成 UUID 每个新命令选择,然后保留返回的手柄进行更新/取消。 申请表必须在每次行动前重新授权听众和每个选定的对象; Pub Sub 注册证书不能确定组织成员。 返回的时间戳是不可改变的服务器元数据,而不是授权证明. 这些方法只有服务器;完整的应用程序存在和节点提供者的等同性仍未完成.

`registerPresenceWatch` 财务报告和审定财务报表 `renewPresenceWatch` 接受此选项 `leaseKey` 观众套接字连接(签名者: `issueTicket({ action: "connect", leaseKey })`) (中文(简体) ). 答案随即 `leaseBinding`数字 : `socket` 当服务保持租赁在套接字的原地重授权 并在最后一个套接字扣上钥匙后十五秒结束时, `request` 当你必须不断更新。 捆绑的手表仍然需要在十五分钟索引保留结束之前重新注册,申请方拥有吊销:在会员终止时取消手表. 参见嵌入式存在表租赁架构页面.

`setPresenceVisibility` 提交订购的批次,最多50个目前的应用程序自主政策修订。 它需要注册 `application` 别名,拒绝更改或部分回复,绝不接受呼叫时钟. `leaseMs` (60 000至900 000美元)要求延长租约;只有在每次政策过渡一次被写成新的订正时才使用,因为反复订正永远不会缩短长期租约。 失败的多硬性操作可能会将限定数额的赠款留给成功的硬性操作;从新读的政策中重试,保留应用程序的披露检查. 缺少或过期的控制被隐藏. 该候选人没有建立完整的应用程序存在或节点对等.

`wakePresencePolicy` 提交应用程序当前条形政策标识:正 `sequence`, (中文(简体) ), `availabilityRevision`, (中文(简体) ), `dndRevision`,一个UUID v4 `changeId` 财务报告和审定财务报表 `reason`. 申请登记必须载有获得许可的经营者 `presence_policy_wake` 能力。 收据系指一项活的持久义务被接受,从未交付. `PRESENCE_POLICY_CONFLICT` 指命令与所保留身份相矛盾(Stale sequence,已改变而无新序列的字段,被再利用的更改ID或被后退的修改);不重试它,取而代之的是重读犬形状态. `PRESENCE_POLICY_RETIRED` 指相同命令的工作已经完成或已过期;以新的顺序恢复并更改ID. `PRESENCE_POLICY_RATE_LIMITED` 表示稍后对同一命令的再试可能成功. 无法获取或模棱两可的结果对有限度的重试保留同样的命令。 客户端不进行自动重试 .

## 常见问题

### @finueva/pub-sub 是什么？

Finueva Pub 子网络 SDK

### 如何安装 @finueva/pub-sub？

在项目目录运行 npm install @finueva/pub-sub，或使用 pnpm add / yarn add / bun add。

### @finueva/pub-sub 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @finueva/pub-sub 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @finueva/pub-sub 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @finueva/pub-sub 可以商用吗？

@finueva/pub-sub 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @finueva/pub-sub 的下载量有多少？

根据 npm 官方下载统计，@finueva/pub-sub 在 2026/10/15 – 2026/11/13 这 30 天内被下载 2,420 次，日均约 81 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @finueva/pub-sub 还在维护吗？

最新版本 0\.14\.0 发布于 2026/10/30（15 天前）；至今共发布 16 个版本，其中过去 12 个月发布了 16 个；首次发布于 2026/08/20。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

