@finueva/pub-sub
使用 @finueva/pub-sub 接收现场活动,管理浏览器推,出票,发布活动.
已确认的Web 连接可选择使用 connect({ deliveryMode: "acknowledged", reauthorization: true, onEvent }) 在经纪人支持现场更新后。 SDK通过同样方式获得新票 getTicket 提供者,请求采取行动 reauthorize (签名像 connect,并重新授权现有订阅。 申请表必须重新验证每张票申请的会话权限。 成功更新不会释放新的打开状态; 实际失败会关闭套接字, 仍然需要应用程序重新连接/ 抓取 。 在启用此选项之前部署经纪人支助。 默认的边界替换行为和遗产v1不变.
Pub Sub是实验性的. 它试图立即交付。 它不保留、重放、顺序、重试、去重复或确认事件.
安装 SDK
pnpm add @finueva/pub-sub
Node.js工具和服务器应用程序需要Node.js 22或更晚.
不透明通道信号
下一个小SDK加 client.createSignalingClient(...) 到峡谷 createPubSubClient 结果。 它为Cloudflare使用相同的配置服务源和WebSocket厂或由明确组成的节点中继器. 信任的服务器客户端 issueChannelTicket({ userId, channel, publish, subscribe, expiresAt }) 申请授权后提供一次性使用补助金; expiresAt 这是一个绝对的毫秒期限,最多提前60秒.
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,从未使用过售票查询参数. 见仓库的 频道架构 用于节点供应商合同和路由构成。 假设服务推出后发布的微量发布;来源可用性并不意味着这些方法存在于安装在更早的SDK中.
API 摘要
浏览器客户端 :
| 方法 | 说明 |
|---|---|
connect() | 打开现场事件连接 . |
enablePush() | 启用当前浏览器安装的推动 . |
disablePush() | 禁用当前浏览器安装的推力 . |
onPush() | 听听推收和通知窃听器. |
服务器客户端 :
| 方法 | 说明 |
|---|---|
issueTicket() | 开出一张订户业务的票. A 类 connect 罚单可以声明 capabilities 例如 presence.hint.subject.v1,则a leaseKey 用于套接字输入的显示表. |
publish() | 向一个应用程序定义的用户发布事件 . |
putInstallation() | 以可选的重试安全突变字段注册安装 . |
observeInstallation() | 请检查date=中的日期值 (帮助). |
deleteInstallation() | 只删除预期的安装化身. |
创建浏览器客户端
提供经认证的用户身份证和 getTicket 函数。 该函数必须请求应用程序服务器的出票 .
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。 。 。 .
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和返回的连接不变.
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(每个浏览器一个共享用户连接),用于设计及其取舍.
启用浏览器推
在控制您的应用程序来源的服务人员中安装收听器.
import { installPubSubServiceWorker } from "@finueva/pub-sub/service-worker";
installPubSubServiceWorker({
notificationIcon: "/notification.png",
openPath: "/inbox",
});
打电话 enablePush() 在用户动作后,例如点击按钮.
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 如果多个用户共享浏览器配置文件.
创建服务器客户端
仅从服务器代码导入服务器入口 .
import { createPubSubServerClient } from "@finueva/pub-sub/server";
const pubSub = createPubSubServerClient({
apiToken: process.env.PUB_SUB_API_TOKEN!,
});
开罚单
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 只有在服务回答安装被移除,本地提供者的代号无法被删除后,应用程序才能完成该代码上的选择退出或签名. 任何其他拒绝都未经证实.
发布事件
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 属性来选择重试或用户界面行为.
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();
}
}
出版非一能. 未知结果后的重试可以不止一次地发送同一事件.
学多点
许可证
麻省理工学院
私人手表(未公布候选人)
服务器入口提供 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 表示稍后对同一命令的再试可能成功. 无法获取或模棱两可的结果对有限度的重试保留同样的命令。 客户端不进行自动重试 .