cross-tab-worker-databus 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -1
- package/README.md +24 -0
- package/README.zh.md +24 -0
- package/dist/centrifuge.js +2 -1
- package/dist/centrifuge.js.map +2 -2
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/chunk-5WRI5ZAA.js.map +7 -0
- package/dist/{chunk-LBXREMZA.js → chunk-PNYWDVTH.js} +31 -4
- package/dist/chunk-PNYWDVTH.js.map +7 -0
- package/dist/cjs/centrifuge.cjs +2127 -0
- package/dist/cjs/centrifuge.cjs.map +7 -0
- package/dist/cjs/hooks.cjs +1975 -0
- package/dist/cjs/hooks.cjs.map +7 -0
- package/dist/cjs/index.cjs +1806 -0
- package/dist/cjs/index.cjs.map +7 -0
- package/dist/core/cluster.d.ts +2 -1
- package/dist/core/cluster.d.ts.map +1 -1
- package/dist/core/data-bus.d.ts +3 -1
- package/dist/core/data-bus.d.ts.map +1 -1
- package/dist/core/routing.d.ts +9 -0
- package/dist/core/routing.d.ts.map +1 -1
- package/dist/hooks.d.ts +31 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +1946 -0
- package/dist/hooks.js.map +7 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +113 -3
- package/dist/index.js.map +3 -3
- package/dist/websocket.d.ts +86 -0
- package/dist/websocket.d.ts.map +1 -0
- package/docs/README.md +1 -0
- package/docs/api.md +74 -0
- package/docs/getting-started.md +7 -0
- package/docs/transports.md +30 -2
- package/docs/zh/README.md +1 -0
- package/docs/zh/api.md +74 -0
- package/docs/zh/getting-started.md +7 -0
- package/docs/zh/transports.md +27 -2
- package/package.json +44 -10
- package/dist/chunk-LBXREMZA.js.map +0 -7
package/docs/api.md
CHANGED
|
@@ -19,6 +19,17 @@ import {
|
|
|
19
19
|
CentrifugeWorkerTransport,
|
|
20
20
|
createCentrifugeDataBus
|
|
21
21
|
} from 'cross-tab-worker-databus/centrifuge';
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
WebSocketTransport,
|
|
25
|
+
createWebSocketDataBus
|
|
26
|
+
} from 'cross-tab-worker-databus';
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
useCrossTabDataBus,
|
|
30
|
+
useCrossTabStatus,
|
|
31
|
+
useCrossTabSubscription
|
|
32
|
+
} from 'cross-tab-worker-databus/hooks';
|
|
22
33
|
```
|
|
23
34
|
|
|
24
35
|
Business integration should prefer `CrossTabDataBus` or `createCentrifugeDataBus`. `WorkerClusterRuntime` is an advanced coordination API.
|
|
@@ -68,6 +79,7 @@ Registers a local subscription and returns a cleanup function.
|
|
|
68
79
|
- The first handler in the current tab registers a cluster subscription.
|
|
69
80
|
- The current tab only leaves the topic after the last handler is released.
|
|
70
81
|
- Subscriptions are automatically queued when the transport is not yet ready.
|
|
82
|
+
- Wildcard subscriptions: a topic ending in `.*` (`chat.*`) matches any remainder, and `*` matches everything. The pattern is routed, owned, and transport-subscribed as a literal channel; publications tagged with a matching concrete topic (or with the pattern itself) are delivered to wildcard handlers. See `topicMatchesPattern` below.
|
|
71
83
|
|
|
72
84
|
### `unsubscribe(topic, handler?)`
|
|
73
85
|
|
|
@@ -216,6 +228,66 @@ Available options:
|
|
|
216
228
|
- `workerFactory`: custom Dedicated Worker loading method
|
|
217
229
|
- `sharedWorkerFactory`: custom SharedWorker loading method
|
|
218
230
|
|
|
231
|
+
## WebSocket Transport Backend
|
|
232
|
+
|
|
233
|
+
A dependency-free transport over a plain WebSocket. Any server speaking the JSON frame protocol below can back the same cross-tab clustering stack (owner dedup, sticky routes, failover) as the Centrifuge backend.
|
|
234
|
+
|
|
235
|
+
### `createWebSocketDataBus<TData>(options)`
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
createWebSocketDataBus<TData>(options): CrossTabDataBus<WebSocketDataBusConfig, TData>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Creates an auto-starting WebSocket DataBus. Defaults: `clusterKey = connection.url`.
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
const bus = createWebSocketDataBus({
|
|
245
|
+
connection: { url: 'wss://example.test/ws' },
|
|
246
|
+
trace: { enabled: true, sink: event => console.log(event) }
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### `WebSocketTransport<TData>`
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
new WebSocketTransport<TData>(connection: WebSocketDataBusConfig)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Implements `DataBusTransport`. Connection lifecycle maps to the DataBus status vocabulary: socket `open` → `connected`, `close` → `disconnected`, `error` → `error` (which triggers DataBus auto-recovery). Subscriptions are re-asserted when a socket reopens in place. Frames dropped while the socket is not open are reported via `handlers.onError`; reopening re-sends subscribe frames.
|
|
257
|
+
|
|
258
|
+
`WebSocketDataBusConfig` fields:
|
|
259
|
+
|
|
260
|
+
- `url` — WebSocket endpoint.
|
|
261
|
+
- `protocols` — optional subprotocol(s) for the handshake.
|
|
262
|
+
- `webSocketFactory` — optional factory `(url, protocols) => WebSocketLike` for tests and non-browser runtimes (defaults to the global `WebSocket`).
|
|
263
|
+
|
|
264
|
+
### Wire protocol
|
|
265
|
+
|
|
266
|
+
JSON text frames:
|
|
267
|
+
|
|
268
|
+
- client → server: `{"op":"subscribe"|"unsubscribe"|"publish","topic":"...","data":...}`
|
|
269
|
+
- server → client: `{"topic":"...","data":...}` for publications. Frames without a string `topic` field are ignored; malformed JSON surfaces via `handlers.onError` without throwing.
|
|
270
|
+
|
|
271
|
+
A pattern-aware server may deliver publications tagged with the concrete topic (recommended); publications tagged with the pattern itself are delivered through the exact-match path.
|
|
272
|
+
|
|
273
|
+
## React Hooks (`cross-tab-worker-databus/hooks`)
|
|
274
|
+
|
|
275
|
+
React (>= 18) is an optional peer dependency; this entry is separate so non-React consumers never load it.
|
|
276
|
+
|
|
277
|
+
### `useCrossTabDataBus(create, deps?)`
|
|
278
|
+
|
|
279
|
+
Creates a bus for the component's lifetime: created on mount, stopped on unmount. StrictMode-safe — the double-invoked effect exercises the same stop/recreate path as BFCache suspend/resume. Returns the active bus or `null` before the first effect (SSR / initial render).
|
|
280
|
+
|
|
281
|
+
Pass a fresh bus per effect run (an inline factory); key recreation through `deps`.
|
|
282
|
+
|
|
283
|
+
### `useCrossTabSubscription(bus, topic, handler)`
|
|
284
|
+
|
|
285
|
+
Attaches a message handler with automatic cleanup. The handler is read through a ref on each delivery, so inline closures do not cause resubscription across re-renders. Queues while `bus` is `null` or the transport is not ready.
|
|
286
|
+
|
|
287
|
+
### `useCrossTabStatus(bus)`
|
|
288
|
+
|
|
289
|
+
Mirrors `bus.onStatus()` into React state and reads the current value synchronously whenever the bus identity changes. Returns `'connecting' | 'connected' | 'disconnected' | 'error'`.
|
|
290
|
+
|
|
219
291
|
## `WorkerClusterRuntime`
|
|
220
292
|
|
|
221
293
|
Advanced API responsible for Worker registration, heartbeat, visibility, routing, BroadcastChannel protocol, and migration. Business modules should not operate on it directly.
|
|
@@ -257,5 +329,7 @@ Selects the actual backend based on `WorkerMode` and capability detection, retur
|
|
|
257
329
|
- `selectLeastLoadedWorker`
|
|
258
330
|
- `selectRebalanceTarget`
|
|
259
331
|
- `hasActiveOwner`
|
|
332
|
+
- `isWildcardTopic(pattern)`
|
|
333
|
+
- `topicMatchesPattern(pattern, topic)` — wildcard matching used by subscriptions: `chat.*` matches `chat.room.1` (segment-boundary prefix), `*` matches everything
|
|
260
334
|
|
|
261
335
|
These pure functions are primarily used for testing, diagnostics, and custom coordination strategies.
|
package/docs/getting-started.md
CHANGED
|
@@ -12,12 +12,19 @@ The package provides the following entry points:
|
|
|
12
12
|
|
|
13
13
|
- `cross-tab-worker-databus`: the core DataBus and transport interfaces
|
|
14
14
|
- `cross-tab-worker-databus/centrifuge`: the built-in Centrifuge Worker transport
|
|
15
|
+
- `cross-tab-worker-databus/centrifuge.worker`: the Dedicated Worker build artifact, loaded by default by the built-in factory; typically no need to reference it directly
|
|
15
16
|
- `cross-tab-worker-databus/centrifuge.shared.worker`: the SharedWorker build artifact, loaded by default by the built-in factory; typically no need to reference it directly
|
|
17
|
+
- `cross-tab-worker-databus/hooks`: optional React hooks adapter (`useCrossTabDataBus`, `useCrossTabSubscription`, `useCrossTabStatus`); React (>= 18) is an optional peer dependency
|
|
18
|
+
- `cross-tab-worker-databus` also exports a zero-dependency native `WebSocketTransport` / `createWebSocketDataBus` for servers that speak plain WebSockets
|
|
19
|
+
|
|
20
|
+
The `cross-tab-worker-databus/centrifuge` entry point relies on the optional peer dependency `centrifuge` (^5.5.3). Install it alongside this package when using the built-in Centrifuge transport: `pnpm add centrifuge`.
|
|
16
21
|
|
|
17
22
|
## 2. Creating an Instance
|
|
18
23
|
|
|
19
24
|
It is recommended to create an instance in the application's infrastructure layer and have other modules import it directly. This way, business modules within the same Tab share the Worker, connection, and Topic references.
|
|
20
25
|
|
|
26
|
+
Both module formats are published: ESM (`import`) and CommonJS (`require` / `dist/cjs`), so CJS bundler configurations and `require()` callers work out of the box.
|
|
27
|
+
|
|
21
28
|
```ts
|
|
22
29
|
import { createCentrifugeDataBus } from 'cross-tab-worker-databus/centrifuge';
|
|
23
30
|
|
package/docs/transports.md
CHANGED
|
@@ -59,8 +59,9 @@ transport only owns the I/O path: connect, subscribe, publish, disconnect.
|
|
|
59
59
|
|
|
60
60
|
Mirror the Centrifuge backend's `centrifuge-protocol.ts`: a discriminated union
|
|
61
61
|
of messages the main thread sends to the Worker (`INIT` / `SUBSCRIBE` /
|
|
62
|
-
`UNSUBSCRIBE` / `PUBLISH` / `STOP`) and a union the
|
|
63
|
-
(`STATUS` / `MESSAGE` / `ERROR`). Keep it
|
|
62
|
+
`UNSUBSCRIBE` / `PUBLISH` / `PUBLISH_BIN` / `PING` / `STOP`) and a union the
|
|
63
|
+
Worker posts back (`STATUS` / `MESSAGE` / `MESSAGE_BIN` / `ERROR`). Keep it
|
|
64
|
+
structured-cloneable (no functions,
|
|
64
65
|
no class instances — `Error` must be serialised).
|
|
65
66
|
|
|
66
67
|
### 2. Implement the session
|
|
@@ -124,8 +125,35 @@ opt in:
|
|
|
124
125
|
}
|
|
125
126
|
```
|
|
126
127
|
|
|
128
|
+
## Built-in: native WebSocket backend
|
|
129
|
+
|
|
130
|
+
The package ships a second real backend, `WebSocketTransport`, proving the
|
|
131
|
+
contract above with zero dependencies. Use it when your server already speaks
|
|
132
|
+
WebSockets and you do not need Centrifugo features.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { createWebSocketDataBus } from 'cross-tab-worker-databus';
|
|
136
|
+
|
|
137
|
+
const bus = createWebSocketDataBus({
|
|
138
|
+
connection: { url: 'wss://example.test/ws' }
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Wire protocol (JSON text frames):
|
|
143
|
+
|
|
144
|
+
- client → server: `{"op":"subscribe"|"unsubscribe"|"publish","topic":"...","data":...}`
|
|
145
|
+
- server → client: publications are `{"topic":"...","data":...}`. Frames
|
|
146
|
+
without a string `topic` are ignored; malformed JSON is reported through
|
|
147
|
+
`handlers.onError` without throwing.
|
|
148
|
+
|
|
149
|
+
Lifecycle mapping: `open` → `connected`, `close` → `disconnected`,
|
|
150
|
+
`error` → `error` (DataBus auto-recovery). Subscribe frames are re-sent when
|
|
151
|
+
the socket reopens in place. A pattern-aware server may tag publications with
|
|
152
|
+
the concrete topic — see wildcard subscriptions in [api.md](./api.md).
|
|
153
|
+
|
|
127
154
|
## Factory entry point
|
|
128
155
|
|
|
156
|
+
|
|
129
157
|
Provide a `create<Backend>DataBus(options)` factory that wires the transport
|
|
130
158
|
into a `CrossTabDataBus`, mirroring `createCentrifugeDataBus`. This is the
|
|
131
159
|
surface most consumers use; it should accept the connection config, cluster
|
package/docs/zh/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|---|---|
|
|
9
9
|
| [快速接入](./getting-started.md) | 安装、创建实例、订阅、发布和销毁 |
|
|
10
10
|
| [配置说明](./configuration.md) | 核心配置、Centrifuge 配置、默认值和约束 |
|
|
11
|
+
| [Transport 后端](./transports.md) | `DataBusTransport` 契约、Worker 协议与第三方后端接入指南 |
|
|
11
12
|
| [API 参考](./api.md) | 公共入口、类型、方法、返回值和行为 |
|
|
12
13
|
| [架构说明](./architecture.md) | Worker 集群、路由、存储、迁移和降级设计 |
|
|
13
14
|
| [能力矩阵](./capabilities.md) | 已实现、未实现和计划待实现的能力矩阵 |
|
package/docs/zh/api.md
CHANGED
|
@@ -19,6 +19,17 @@ import {
|
|
|
19
19
|
CentrifugeWorkerTransport,
|
|
20
20
|
createCentrifugeDataBus
|
|
21
21
|
} from 'cross-tab-worker-databus/centrifuge';
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
WebSocketTransport,
|
|
25
|
+
createWebSocketDataBus
|
|
26
|
+
} from 'cross-tab-worker-databus';
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
useCrossTabDataBus,
|
|
30
|
+
useCrossTabStatus,
|
|
31
|
+
useCrossTabSubscription
|
|
32
|
+
} from 'cross-tab-worker-databus/hooks';
|
|
22
33
|
```
|
|
23
34
|
|
|
24
35
|
业务接入优先使用 `CrossTabDataBus` 或 `createCentrifugeDataBus`。`WorkerClusterRuntime` 属于高级协调 API。
|
|
@@ -68,6 +79,7 @@ subscribe(
|
|
|
68
79
|
- 当前 Tab 第一个 handler 会登记集群订阅。
|
|
69
80
|
- 最后一个 handler 释放后,当前 Tab 才退出该 Topic。
|
|
70
81
|
- transport 尚未 ready 时订阅自动排队。
|
|
82
|
+
- 通配符订阅:以 `.*` 结尾的 Topic(如 `chat.*`)匹配任意后缀,`*` 匹配全部。pattern 以字面量参与路由、归属与传输订阅;携带匹配的具体 topic(或 pattern 本身)的发布都会投递给通配 handler。匹配规则见下方 `topicMatchesPattern`。
|
|
71
83
|
|
|
72
84
|
### `unsubscribe(topic, handler?)`
|
|
73
85
|
|
|
@@ -216,6 +228,66 @@ const transport = new CentrifugeWorkerTransport({
|
|
|
216
228
|
- `workerFactory`:自定义 Dedicated Worker 加载方式
|
|
217
229
|
- `sharedWorkerFactory`:自定义 SharedWorker 加载方式
|
|
218
230
|
|
|
231
|
+
## WebSocket 传输后端
|
|
232
|
+
|
|
233
|
+
基于原生 WebSocket 的零依赖传输。任何实现下列 JSON 帧协议的服务器都能驱动与 Centrifuge 后端相同的跨 Tab 集群栈(owner 去重、粘性路由、故障转移)。
|
|
234
|
+
|
|
235
|
+
### `createWebSocketDataBus<TData>(options)`
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
createWebSocketDataBus<TData>(options): CrossTabDataBus<WebSocketDataBusConfig, TData>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
创建自动启动的 WebSocket DataBus。默认值:`clusterKey = connection.url`。
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
const bus = createWebSocketDataBus({
|
|
245
|
+
connection: { url: 'wss://example.test/ws' },
|
|
246
|
+
trace: { enabled: true, sink: event => console.log(event) }
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### `WebSocketTransport<TData>`
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
new WebSocketTransport<TData>(connection: WebSocketDataBusConfig)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
实现 `DataBusTransport`。连接生命周期直接映射 DataBus 状态:socket `open` → `connected`,`close` → `disconnected`,`error` → `error`(触发 DataBus 自动恢复)。socket 原地重连时会自动重发订阅;socket 未打开期间被丢弃的帧通过 `handlers.onError` 上报,重开后自动补发订阅帧。
|
|
257
|
+
|
|
258
|
+
`WebSocketDataBusConfig` 字段:
|
|
259
|
+
|
|
260
|
+
- `url` — WebSocket 端点。
|
|
261
|
+
- `protocols` — 可选的握手子协议。
|
|
262
|
+
- `webSocketFactory` — 可选工厂 `(url, protocols) => WebSocketLike`,用于测试与非浏览器运行时(默认使用全局 `WebSocket`)。
|
|
263
|
+
|
|
264
|
+
### 线协议
|
|
265
|
+
|
|
266
|
+
JSON 文本帧:
|
|
267
|
+
|
|
268
|
+
- client → server:`{"op":"subscribe"|"unsubscribe"|"publish","topic":"...","data":...}`
|
|
269
|
+
- server → client:发布为 `{"topic":"...","data":...}`。没有字符串 `topic` 字段的帧被忽略;非法 JSON 通过 `handlers.onError` 上报而不会抛出。
|
|
270
|
+
|
|
271
|
+
支持 pattern 的服务器建议以具体 topic 标注发布;以 pattern 本身标注的发布走精确匹配路径投递。
|
|
272
|
+
|
|
273
|
+
## React Hooks(`cross-tab-worker-databus/hooks`)
|
|
274
|
+
|
|
275
|
+
React(>= 18)是可选 peer 依赖;独立入口保证非 React 消费者不会加载它。
|
|
276
|
+
|
|
277
|
+
### `useCrossTabDataBus(create, deps?)`
|
|
278
|
+
|
|
279
|
+
创建随组件生命周期存活的 bus:挂载时创建,卸载时停止。StrictMode 安全——effect 双调用走的是与 BFCache 挂起/恢复相同的停止/重建路径。返回当前 bus;首次 effect 之前(SSR / 初始渲染)为 `null`。
|
|
280
|
+
|
|
281
|
+
每次 effect 返回一个全新 bus(内联工厂即可);需要重建时通过 `deps` 控制。
|
|
282
|
+
|
|
283
|
+
### `useCrossTabSubscription(bus, topic, handler)`
|
|
284
|
+
|
|
285
|
+
登记消息 handler 并自动清理。handler 经由 ref 在每次投递时读取,因此内联闭包不会导致重渲染时的重订阅。`bus` 为 `null` 或 transport 未 ready 时自动排队。
|
|
286
|
+
|
|
287
|
+
### `useCrossTabStatus(bus)`
|
|
288
|
+
|
|
289
|
+
把 `bus.onStatus()` 镜像为 React 状态,bus 身份变化时同步读取当前值。返回 `'connecting' | 'connected' | 'disconnected' | 'error'`。
|
|
290
|
+
|
|
219
291
|
## `WorkerClusterRuntime`
|
|
220
292
|
|
|
221
293
|
高级 API,负责 Worker 注册、心跳、可见性、路由、BroadcastChannel 协议和迁移。业务模块不应直接操作它。
|
|
@@ -257,5 +329,7 @@ const transport = new CentrifugeWorkerTransport({
|
|
|
257
329
|
- `selectLeastLoadedWorker`
|
|
258
330
|
- `selectRebalanceTarget`
|
|
259
331
|
- `hasActiveOwner`
|
|
332
|
+
- `isWildcardTopic(pattern)`
|
|
333
|
+
- `topicMatchesPattern(pattern, topic)` — 订阅使用的通配匹配:`chat.*` 匹配 `chat.room.1`(按段前缀),`*` 匹配全部
|
|
260
334
|
|
|
261
335
|
这些纯函数主要用于测试、诊断和自定义协调策略。
|
|
@@ -12,12 +12,19 @@ pnpm add cross-tab-worker-databus
|
|
|
12
12
|
|
|
13
13
|
- `cross-tab-worker-databus`:核心 DataBus 和 transport 接口
|
|
14
14
|
- `cross-tab-worker-databus/centrifuge`:内置 Centrifuge Worker transport
|
|
15
|
+
- `cross-tab-worker-databus/centrifuge.worker`:Dedicated Worker 构建产物,默认由内置 factory 加载,通常无需直接引用
|
|
15
16
|
- `cross-tab-worker-databus/centrifuge.shared.worker`:SharedWorker 构建产物,默认由内置 factory 加载,通常无需直接引用
|
|
17
|
+
- `cross-tab-worker-databus/hooks`:可选的 React hooks 适配层(`useCrossTabDataBus`、`useCrossTabSubscription`、`useCrossTabStatus`);React(>= 18)为可选 peer 依赖
|
|
18
|
+
- `cross-tab-worker-databus` 同时导出零依赖的原生 `WebSocketTransport` / `createWebSocketDataBus`,适用于本身使用 WebSocket 的服务器
|
|
19
|
+
|
|
20
|
+
`cross-tab-worker-databus/centrifuge` 入口依赖可选 peer dependency `centrifuge`(^5.5.3)。使用内置 Centrifuge transport 时请一并安装:`pnpm add centrifuge`。
|
|
16
21
|
|
|
17
22
|
## 2. 创建实例
|
|
18
23
|
|
|
19
24
|
建议在应用基础设施层创建一个实例,其他模块直接导入。这样同一 Tab 内的业务模块会共享 Worker、连接和 Topic 引用。
|
|
20
25
|
|
|
26
|
+
包同时发布 ESM 与 CommonJS 双格式:`import` 与 `require()`(`dist/cjs`)均可直接使用,CJS bundler 配置无需额外处理。
|
|
27
|
+
|
|
21
28
|
```ts
|
|
22
29
|
import { createCentrifugeDataBus } from 'cross-tab-worker-databus/centrifuge';
|
|
23
30
|
|
package/docs/zh/transports.md
CHANGED
|
@@ -54,8 +54,9 @@ DataBus 层负责跨 Tab 协调(BroadcastChannel 控制面、localStorage 路
|
|
|
54
54
|
### 1. 定义你的 Worker 协议
|
|
55
55
|
|
|
56
56
|
参照 Centrifuge 后端的 `centrifuge-protocol.ts`:一个主线程发给 Worker 的
|
|
57
|
-
判别联合(`INIT` / `SUBSCRIBE` / `UNSUBSCRIBE` / `PUBLISH` / `
|
|
58
|
-
Worker 回传的联合(`STATUS` / `MESSAGE` / `
|
|
57
|
+
判别联合(`INIT` / `SUBSCRIBE` / `UNSUBSCRIBE` / `PUBLISH` / `PUBLISH_BIN` /
|
|
58
|
+
`PING` / `STOP`)和一个 Worker 回传的联合(`STATUS` / `MESSAGE` / `MESSAGE_BIN` /
|
|
59
|
+
`ERROR`)。保持结构化克隆安全
|
|
59
60
|
(无函数、无类实例——`Error` 必须序列化)。
|
|
60
61
|
|
|
61
62
|
### 2. 实现 session
|
|
@@ -113,8 +114,32 @@ shared worker):
|
|
|
113
114
|
}
|
|
114
115
|
```
|
|
115
116
|
|
|
117
|
+
## 内置:原生 WebSocket 后端
|
|
118
|
+
|
|
119
|
+
包内自带第二个真实后端 `WebSocketTransport`,以零依赖验证了上述契约。当你的
|
|
120
|
+
服务器本身使用 WebSocket、且不需要 Centrifugo 特性时可以直接使用。
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { createWebSocketDataBus } from 'cross-tab-worker-databus';
|
|
124
|
+
|
|
125
|
+
const bus = createWebSocketDataBus({
|
|
126
|
+
connection: { url: 'wss://example.test/ws' }
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
线协议(JSON 文本帧):
|
|
131
|
+
|
|
132
|
+
- client → server:`{"op":"subscribe"|"unsubscribe"|"publish","topic":"...","data":...}`
|
|
133
|
+
- server → client:发布为 `{"topic":"...","data":...}`。没有字符串 `topic` 的帧
|
|
134
|
+
会被忽略;非法 JSON 通过 `handlers.onError` 上报而不会抛出。
|
|
135
|
+
|
|
136
|
+
生命周期映射:`open` → `connected`,`close` → `disconnected`,`error` → `error`
|
|
137
|
+
(触发 DataBus 自动恢复)。socket 原地重连时自动重发订阅帧。支持 pattern 的
|
|
138
|
+
服务器可以以具体 topic 标注发布——见 [api.md](../api.md) 中的通配符订阅。
|
|
139
|
+
|
|
116
140
|
## 工厂入口
|
|
117
141
|
|
|
142
|
+
|
|
118
143
|
提供一个 `create<Backend>DataBus(options)` 工厂,把 transport 接入
|
|
119
144
|
`CrossTabDataBus`,与 `createCentrifugeDataBus` 对称。这是大多数消费者使用的
|
|
120
145
|
界面;它应接受连接配置、cluster key(默认为连接 URL),并把 trace /
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cross-tab-worker-databus",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Framework-agnostic cross-tab data bus with Dedicated/Shared Worker clustering and Centrifuge support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,48 +29,82 @@
|
|
|
29
29
|
"README.md",
|
|
30
30
|
"LICENSE"
|
|
31
31
|
],
|
|
32
|
-
"main": "./dist/index.
|
|
32
|
+
"main": "./dist/cjs/index.cjs",
|
|
33
33
|
"module": "./dist/index.js",
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
35
|
"exports": {
|
|
36
36
|
".": {
|
|
37
37
|
"types": "./dist/index.d.ts",
|
|
38
|
-
"import": "./dist/index.js"
|
|
38
|
+
"import": "./dist/index.js",
|
|
39
|
+
"require": "./dist/cjs/index.cjs"
|
|
39
40
|
},
|
|
40
41
|
"./centrifuge": {
|
|
41
42
|
"types": "./dist/centrifuge.d.ts",
|
|
42
|
-
"import": "./dist/centrifuge.js"
|
|
43
|
+
"import": "./dist/centrifuge.js",
|
|
44
|
+
"require": "./dist/cjs/centrifuge.cjs"
|
|
45
|
+
},
|
|
46
|
+
"./centrifuge.worker": {
|
|
47
|
+
"types": "./dist/workers/centrifuge.worker.d.ts",
|
|
48
|
+
"default": "./dist/centrifuge.worker.js"
|
|
49
|
+
},
|
|
50
|
+
"./centrifuge.shared.worker": {
|
|
51
|
+
"types": "./dist/workers/centrifuge.shared.worker.d.ts",
|
|
52
|
+
"default": "./dist/centrifuge.shared.worker.js"
|
|
53
|
+
},
|
|
54
|
+
"./hooks": {
|
|
55
|
+
"types": "./dist/hooks.d.ts",
|
|
56
|
+
"import": "./dist/hooks.js",
|
|
57
|
+
"require": "./dist/cjs/hooks.cjs"
|
|
43
58
|
},
|
|
44
|
-
"./centrifuge.worker": "./dist/centrifuge.worker.js",
|
|
45
|
-
"./centrifuge.shared.worker": "./dist/centrifuge.shared.worker.js",
|
|
46
59
|
"./package.json": "./package.json"
|
|
47
60
|
},
|
|
61
|
+
"sideEffects": [
|
|
62
|
+
"./dist/centrifuge.worker.js",
|
|
63
|
+
"./dist/centrifuge.shared.worker.js"
|
|
64
|
+
],
|
|
48
65
|
"scripts": {
|
|
49
66
|
"build": "node scripts/build.mjs",
|
|
50
|
-
"check": "pnpm typecheck && pnpm
|
|
67
|
+
"check": "pnpm typecheck && pnpm build && pnpm test",
|
|
51
68
|
"examples": "node scripts/serve-examples.mjs",
|
|
69
|
+
"lint": "eslint .",
|
|
52
70
|
"test": "vitest run",
|
|
53
71
|
"test:watch": "vitest",
|
|
72
|
+
"test:coverage": "vitest run --coverage",
|
|
54
73
|
"test:e2e": "pnpm build && playwright test",
|
|
55
|
-
"typecheck": "tsc --noEmit"
|
|
74
|
+
"typecheck": "tsc --noEmit",
|
|
75
|
+
"prepublishOnly": "pnpm check"
|
|
56
76
|
},
|
|
57
77
|
"peerDependencies": {
|
|
58
|
-
"centrifuge": "^5.5.3"
|
|
78
|
+
"centrifuge": "^5.5.3",
|
|
79
|
+
"react": ">=18"
|
|
59
80
|
},
|
|
60
81
|
"peerDependenciesMeta": {
|
|
61
82
|
"centrifuge": {
|
|
62
83
|
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"react": {
|
|
86
|
+
"optional": true
|
|
63
87
|
}
|
|
64
88
|
},
|
|
65
89
|
"devDependencies": {
|
|
90
|
+
"@eslint/js": "^9.39.5",
|
|
66
91
|
"@playwright/test": "^1.62.1",
|
|
92
|
+
"@testing-library/react": "^16.3.3",
|
|
67
93
|
"@types/node": "^24.0.0",
|
|
94
|
+
"@types/react": "^18.3.31",
|
|
95
|
+
"@vitest/coverage-v8": "^3.2.7",
|
|
68
96
|
"esbuild": "^0.25.0",
|
|
97
|
+
"eslint": "^9.39.4",
|
|
98
|
+
"globals": "^17.11.0",
|
|
99
|
+
"jsdom": "^25.0.1",
|
|
100
|
+
"react": "^18.3.1",
|
|
101
|
+
"react-dom": "^18.3.1",
|
|
69
102
|
"typescript": "^5.9.0",
|
|
103
|
+
"typescript-eslint": "^8.68.0",
|
|
70
104
|
"vitest": "^3.2.0"
|
|
71
105
|
},
|
|
72
106
|
"engines": {
|
|
73
107
|
"node": ">=18.0.0"
|
|
74
108
|
},
|
|
75
109
|
"packageManager": "pnpm@10.14.0"
|
|
76
|
-
}
|
|
110
|
+
}
|