react-ws-context 0.3.0 → 0.4.1
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 +33 -0
- package/README.md +105 -82
- package/README.zh-TW.md +93 -83
- package/dist/index.d.mts +30 -29
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +71 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.zh-TW.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
> **English:** [README.md](./README.md)
|
|
2
|
-
|
|
3
1
|
# react-ws-context
|
|
4
2
|
|
|
5
3
|
[](https://www.npmjs.com/package/react-ws-context)
|
|
6
4
|
[](https://www.npmjs.com/package/react-ws-context)
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
> **English:** [README.md](./README.md)
|
|
7
|
+
|
|
8
|
+
React 用的 **WebSocket 連線層**套件。將連線生命週期、可訂閱狀態與訊息事件分離,避免連線 status 或高頻訊息更新拖垮整棵元件樹。
|
|
9
9
|
|
|
10
10
|
> **維護者:** [GaiaYang](https://github.com/GaiaYang)
|
|
11
11
|
> **原始碼:** [github.com/GaiaYang/react-ws](https://github.com/GaiaYang/react-ws)(monorepo 內路徑 `packages/react-ws`)
|
|
@@ -14,7 +14,7 @@ React 用的 WebSocket **連線層**套件。將連線生命週期、可訂閱
|
|
|
14
14
|
|
|
15
15
|
- **零 runtime 依賴** — 僅需 `react >= 18`(peer dependency)
|
|
16
16
|
- **設定凍結** — `url`、`reconnectMs` 等在 `createWsContext` 時固定;執行期以 `connect` / `disconnect` 控制
|
|
17
|
-
- **渲染隔離** — 連線層 state(健康/佇列/重連)走外部 store
|
|
17
|
+
- **渲染隔離** — 連線層 state(健康/佇列/重連)走外部 store;訊息經 event emitter 傳遞,以 `useWsEvents` 訂閱(不寫入 React state)
|
|
18
18
|
- **可選探活** — 週期性 ping/pong 偵測,逾時主動關閉 socket 以觸發重連
|
|
19
19
|
- **可選 outbound 佇列** — 未 OPEN 時暫存待送訊息,連線成功後 flush
|
|
20
20
|
|
|
@@ -87,12 +87,13 @@ function Chat() {
|
|
|
87
87
|
createWsContext(options)
|
|
88
88
|
│
|
|
89
89
|
├── WsProvider 管理 WebSocket 實例、重連、探活、outbound 佇列
|
|
90
|
-
├── useWsActions() 連線操作(send / connect / disconnect),不觸發重繪
|
|
91
|
-
├── useWsStore() 訂閱連線層 state
|
|
92
|
-
└── useWsEvents()
|
|
90
|
+
├── useWsActions() 連線操作(send / connect / disconnect / getStatus),不觸發重繪
|
|
91
|
+
├── useWsStore() 訂閱連線層 state:健康/佇列/重連
|
|
92
|
+
└── useWsEvents() 訂閱 open / message / error / close 事件
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
- **同一應用可多次呼叫 `createWsContext`**,每次產生一組互不共用的 Provider 與 hooks(例如同時連業務 WS 與通知 WS)。
|
|
96
|
+
- **Provider 內部** — 各 `WsProvider` 持有獨立的 store 與 event emitter(非公開 API);actions 在 `WsProvider` 內以 `useMemo` 組裝後注入 Context。
|
|
96
97
|
- **`WsState` 只放連線層、低頻欄位** — 連線健康(`status`、`phase`)、outbound 佇列(如未來 `pendingCount`)、重連(`reconnectAttempt`)。**不放**訊息 payload 或業務資料。
|
|
97
98
|
- **訊息與錯誤事件** — 請用 `useWsEvents`;訊息歷史請自行寫入 state、cache 或外部 store。
|
|
98
99
|
- **連線錯誤不反映在 `WsStatus`** — 請用 `useWsEvents("error", …)` 處理;原生 `error` 事件後通常緊接 `close`。
|
|
@@ -107,16 +108,16 @@ createWsContext(options)
|
|
|
107
108
|
|
|
108
109
|
#### 參數:`CreateWsContextOptions`
|
|
109
110
|
|
|
110
|
-
| 欄位 | 型別 | 預設 | 說明
|
|
111
|
-
| ------------------ | ----------------------------------------- | -------- |
|
|
112
|
-
| `url` | `string` | (必填) | WebSocket 連線網址
|
|
113
|
-
| `protocols` | `string \| string[]` | — | 傳入 `new WebSocket(url, protocols)` 的子協定
|
|
114
|
-
| `autoConnect` | `boolean` | `true` |
|
|
115
|
-
| `reconnectMs` | `number` | `0` | 非主動斷線後的重連間隔(毫秒);`0` 表示不重連
|
|
116
|
-
| `reconnectMax` | `number` | `0` |
|
|
117
|
-
| `outgoingQueueMax` | `number` | `0` | 未 OPEN 時 outbound 佇列上限;`0` 關閉佇列
|
|
118
|
-
| `parse` | `(data: MessageEvent["data"]) => unknown` | 見下方 | 將原始 `MessageEvent.data` 轉成業務資料
|
|
119
|
-
| `liveness` | `LivenessOptions` | — | 探活設定;省略則不啟用
|
|
111
|
+
| 欄位 | 型別 | 預設 | 說明 |
|
|
112
|
+
| ------------------ | ----------------------------------------- | -------- | ---------------------------------------------------------------- |
|
|
113
|
+
| `url` | `string` | (必填) | WebSocket 連線網址 |
|
|
114
|
+
| `protocols` | `string \| string[]` | — | 傳入 `new WebSocket(url, protocols)` 的子協定 |
|
|
115
|
+
| `autoConnect` | `boolean` | `true` | WsProvider 載入時是否自動連線 |
|
|
116
|
+
| `reconnectMs` | `number` | `0` | 非主動斷線後的重連間隔(毫秒);`0` 表示不重連 |
|
|
117
|
+
| `reconnectMax` | `number` | `0` | 非主動斷線後最多自動重連幾次;`0` 不限制(需 `reconnectMs > 0`) |
|
|
118
|
+
| `outgoingQueueMax` | `number` | `0` | 未 OPEN 時 outbound 佇列上限;`0` 關閉佇列 |
|
|
119
|
+
| `parse` | `(data: MessageEvent["data"]) => unknown` | 見下方 | 將原始 `MessageEvent.data` 轉成業務資料 |
|
|
120
|
+
| `liveness` | `LivenessOptions` | — | 探活設定;省略則不啟用 |
|
|
120
121
|
|
|
121
122
|
**預設 `parse` 行為:**
|
|
122
123
|
|
|
@@ -138,12 +139,13 @@ createWsContext(options)
|
|
|
138
139
|
|
|
139
140
|
負責建立、維護與銷毀原生 `WebSocket` 實例。
|
|
140
141
|
|
|
141
|
-
| 行為 | 說明
|
|
142
|
-
| --------------------------- |
|
|
143
|
-
|
|
|
144
|
-
| unmount |
|
|
145
|
-
|
|
|
146
|
-
|
|
|
142
|
+
| 行為 | 說明 |
|
|
143
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
144
|
+
| `WsProvider` 載入且 `autoConnect: true` | 自動連線 |
|
|
145
|
+
| unmount | 取消重連(`reconnectAttempt` 與 `reconnectExhausted` 歸零)、停止探活、清空 outbound 佇列;store 同步為 `status: "closed"`、`phase: "idle"`;關閉 socket 並 emit `close`(reason: `"provider unmount"`) |
|
|
146
|
+
| `disconnect()` | 同 unmount 的 cleanup 與 store 重置,但不觸發自動重連;emit `close`(reason: `"client disconnect"`) |
|
|
147
|
+
| 重連 | 非主動斷線且 `reconnectMs > 0` 時,以固定間隔重試(無 exponential backoff);`reconnectMax > 0` 時超過次數即停止 |
|
|
148
|
+
| `connect()` 時已有舊 socket | 先關閉舊 socket 並 emit `close`(reason: `"reconnect"`),再建立新連線(手動 connect 或自動重連皆同) |
|
|
147
149
|
|
|
148
150
|
---
|
|
149
151
|
|
|
@@ -151,27 +153,29 @@ createWsContext(options)
|
|
|
151
153
|
|
|
152
154
|
必須在對應的 `WsProvider` 內使用。回傳值以 `useMemo` 穩定引用,**不會**因 store 或訊息更新而重繪元件。
|
|
153
155
|
|
|
154
|
-
| 方法 | 簽名 | 說明
|
|
155
|
-
| ------------ | ---------------------------- |
|
|
156
|
-
| `send` | `(data) => boolean` | 傳送原始資料(`string`、`ArrayBuffer`、`Blob` 等)。已 OPEN 則立即送出;否則視佇列設定入隊
|
|
157
|
-
| `sendJson` | `(data: unknown) => boolean` | `JSON.stringify` 後呼叫 `send`
|
|
158
|
-
| `connect` | `() => void` | 建立連線;若已有連線會先關閉舊 socket
|
|
159
|
-
| `disconnect` | `() => void` |
|
|
160
|
-
| `getStatus` | `() => WsStatus` | 讀取當下 status;不訂閱、不觸發渲染
|
|
156
|
+
| 方法 | 簽名 | 說明 |
|
|
157
|
+
| ------------ | ---------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
158
|
+
| `send` | `(data) => boolean` | 傳送原始資料(`string`、`ArrayBuffer`、`Blob` 等)。已 OPEN 則立即送出;否則視佇列設定入隊 |
|
|
159
|
+
| `sendJson` | `(data: unknown) => boolean` | `JSON.stringify` 後呼叫 `send`;回傳值同 `send`,無法序列化時為 `false` |
|
|
160
|
+
| `connect` | `() => void` | 建立連線;若已有連線會先關閉舊 socket(見 `WsProvider`) |
|
|
161
|
+
| `disconnect` | `() => void` | 主動斷線;store 設為 `phase: "idle"`、`status: "closed"`,**不**觸發自動重連;清空 outbound 佇列 |
|
|
162
|
+
| `getStatus` | `() => WsStatus` | 讀取當下 status;不訂閱、不觸發渲染 |
|
|
161
163
|
|
|
162
164
|
**`send` / `sendJson` 回傳值:**
|
|
163
165
|
|
|
164
166
|
- `true` — 已送出,或已成功入隊
|
|
165
|
-
- `false` —
|
|
167
|
+
- `false` — 未送出:佇列已滿、佇列關閉,或 `sendJson` 無法序列化
|
|
166
168
|
|
|
167
169
|
---
|
|
168
170
|
|
|
169
171
|
### `useWsStore()`
|
|
170
172
|
|
|
171
|
-
必須在對應的 `WsProvider` 內使用。底層以 `useSyncExternalStore` 訂閱外部 store
|
|
173
|
+
必須在對應的 `WsProvider` 內使用。底層以 `useSyncExternalStore` 訂閱外部 store;**partial 內欄位值未變時不會通知訂閱者**(shallow compare)。
|
|
172
174
|
|
|
173
175
|
`WsState` 定位:**連線健康/outbound 佇列/重連** 等低頻、連線生命週期資訊。高頻訊息請用 `useWsEvents("message", …)`,不要寫進 store。
|
|
174
176
|
|
|
177
|
+
**建議:** 以 selector 只訂閱需要的欄位(例如 `(s) => s.phase`)。不帶 selector 的 `useWsStore()` 會訂閱整份 state,任一欄位變更都會觸發 re-render。
|
|
178
|
+
|
|
175
179
|
```ts
|
|
176
180
|
useWsStore(): WsState
|
|
177
181
|
useWsStore<T>(selector: (state: WsState) => T): T
|
|
@@ -193,9 +197,9 @@ interface WsState {
|
|
|
193
197
|
}
|
|
194
198
|
```
|
|
195
199
|
|
|
196
|
-
| 適合放進 store
|
|
197
|
-
|
|
|
198
|
-
| `status`、`phase`、重連進度(`reconnectAttempt` / `reconnectExhausted
|
|
200
|
+
| 適合放進 store | 不適合 |
|
|
201
|
+
| ---------------------------------------------------------------------------------------------------- | ------------------------------------- |
|
|
202
|
+
| `status`、`phase`、重連進度(`reconnectAttempt` / `reconnectExhausted`)、探活/stall 等連線健康摘要 | `lastMessage`、訊息歷史、業務 payload |
|
|
199
203
|
|
|
200
204
|
`CreateWsContextOptions`(如 `url`、`reconnectMax`)在 `createWsContext` 時凍結,**不在** `WsState`;UI 若需顯示 `n/max` 請自行保存設定值,或訂閱時與 store 欄位組合。
|
|
201
205
|
|
|
@@ -212,17 +216,17 @@ interface WsState {
|
|
|
212
216
|
|
|
213
217
|
#### `WsPhase`
|
|
214
218
|
|
|
215
|
-
| 值
|
|
216
|
-
|
|
|
217
|
-
| `idle`
|
|
218
|
-
| `connecting`
|
|
219
|
-
| `open`
|
|
220
|
-
| `reconnecting`
|
|
221
|
-
| `stopped`
|
|
219
|
+
| 值 | 意義 |
|
|
220
|
+
| -------------- | --------------------------------------------------------------------- |
|
|
221
|
+
| `idle` | 未連線、未排程重連(初始或手動 `disconnect()`) |
|
|
222
|
+
| `connecting` | 首次或手動 `connect()` 連線中 |
|
|
223
|
+
| `open` | 已連線 |
|
|
224
|
+
| `reconnecting` | 自動重連週期(等待計時器或連線中);搭配 `status`、`reconnectAttempt` |
|
|
225
|
+
| `stopped` | 不會再自動重連;`reconnectExhausted` 區分達上限或未啟用重連 |
|
|
222
226
|
|
|
223
227
|
`status` 與 `phase` 常同時變化,但語意不同。例如 `phase === "reconnecting"` 且 `status === "closed"` 表示正在等待重連計時器;`status === "connecting"` 則表示計時器已觸發、正在嘗試連線。
|
|
224
228
|
|
|
225
|
-
|
|
229
|
+
**範例:**
|
|
226
230
|
|
|
227
231
|
```tsx
|
|
228
232
|
const phase = useWsStore((s) => s.phase);
|
|
@@ -252,19 +256,23 @@ const canDisconnect =
|
|
|
252
256
|
|
|
253
257
|
- `handler` 以 ref 保存最新引用,callback 重建**不會**導致重新訂閱
|
|
254
258
|
- `type` 變更**會**重新訂閱
|
|
259
|
+
- 意外斷線時,`close` handler 觸發前 store 已更新為 `status: "closed"` 及對應 `phase`(`reconnecting` / `stopped` 等)
|
|
260
|
+
- 主動 `disconnect()` 或 Provider unmount 亦同:先更新 store,再 emit `close`
|
|
255
261
|
- 需監聽多種事件時,分別呼叫多次 `useWsEvents`
|
|
256
262
|
|
|
257
263
|
---
|
|
258
264
|
|
|
259
|
-
###
|
|
265
|
+
### 探活
|
|
266
|
+
|
|
267
|
+
透過 `createWsContext({ liveness: { … } })` 啟用。連線 OPEN 後週期性送出應用層 ping(經 `send` 送 JSON,非 WebSocket 控制帧);若在 `timeoutMs` 內未收到符合條件的 pong,主動 `close()` socket(進而觸發重連流程)。
|
|
260
268
|
|
|
261
|
-
|
|
269
|
+
`liveness` 選項形狀如下:
|
|
262
270
|
|
|
263
271
|
```ts
|
|
264
272
|
interface LivenessOptions {
|
|
265
273
|
intervalMs: number; // ping 間隔(毫秒)
|
|
266
274
|
timeoutMs: number; // 等待 pong 逾時(毫秒)
|
|
267
|
-
ping: unknown | (() => unknown); // ping
|
|
275
|
+
ping: unknown | (() => unknown); // ping payload;函式則每次動態產生
|
|
268
276
|
isPong: (data: unknown) => boolean; // 判定傳入 data 是否為 pong
|
|
269
277
|
}
|
|
270
278
|
```
|
|
@@ -287,7 +295,7 @@ createWsContext({
|
|
|
287
295
|
});
|
|
288
296
|
```
|
|
289
297
|
|
|
290
|
-
探活期間,`onmessage` 收到的每一筆資料都會先經 `isPong` 判定;若為 pong
|
|
298
|
+
探活期間,`onmessage` 收到的每一筆資料都會先經 `isPong` 判定;若為 pong 則清除逾時計時,並照常 emit `"message"` 事件。ping payload 一律以 `JSON.stringify` 送出(僅支援 JSON 格式)。
|
|
291
299
|
|
|
292
300
|
---
|
|
293
301
|
|
|
@@ -295,14 +303,14 @@ createWsContext({
|
|
|
295
303
|
|
|
296
304
|
當 `outgoingQueueMax > 0` 時:
|
|
297
305
|
|
|
298
|
-
| 時機 | 行為
|
|
299
|
-
| ------------------------ |
|
|
300
|
-
| `send` 且 socket 未 OPEN | 訊息入隊(FIFO)
|
|
301
|
-
| 佇列已滿 | 回傳 `false`,**不**丟棄舊訊息
|
|
302
|
-
| socket OPEN | 依序 flush 全部佇列
|
|
303
|
-
| `disconnect()` |
|
|
304
|
-
| `WsProvider` unmount |
|
|
305
|
-
| 自動重連等待期間 | **保留**佇列
|
|
306
|
+
| 時機 | 行為 |
|
|
307
|
+
| ------------------------ | --------------------------------------------------------- |
|
|
308
|
+
| `send` 且 socket 未 OPEN | 訊息入隊(FIFO) |
|
|
309
|
+
| 佇列已滿 | 回傳 `false`,**不**丟棄舊訊息 |
|
|
310
|
+
| socket OPEN | 依序 flush 全部佇列 |
|
|
311
|
+
| `disconnect()` | 清空佇列;store 設為 `idle` / `closed`(見 `WsProvider`) |
|
|
312
|
+
| `WsProvider` unmount | 清空佇列;store 同步(見 `WsProvider`) |
|
|
313
|
+
| 自動重連等待期間 | **保留**佇列 |
|
|
306
314
|
|
|
307
315
|
---
|
|
308
316
|
|
|
@@ -310,14 +318,15 @@ createWsContext({
|
|
|
310
318
|
|
|
311
319
|
自 `react-ws-context` 主入口匯出:
|
|
312
320
|
|
|
313
|
-
| 型別 | 說明
|
|
314
|
-
| ------------------------ |
|
|
315
|
-
| `CreateWsContextOptions` | `createWsContext` 的選項
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
321
|
+
| 型別 | 說明 |
|
|
322
|
+
| ------------------------ | --------------------------------------------------- |
|
|
323
|
+
| `CreateWsContextOptions` | `createWsContext` 的選項 |
|
|
324
|
+
| `LivenessOptions` | `createWsContext` 的 `liveness` 選項 |
|
|
325
|
+
| `WsContextValue` | `useWsActions()` 回傳型別 |
|
|
326
|
+
| `WsEvents` | 事件名稱與 handler 的型別對應 |
|
|
327
|
+
| `WsStatus` | WebSocket 連線狀態(`WsState` 的一環) |
|
|
319
328
|
| `WsPhase` | Provider 連線意圖與重連策略階段(`WsState` 的一環) |
|
|
320
|
-
| `WsState` | 可訂閱 store 的 state 形狀(連線健康/佇列/重連)
|
|
329
|
+
| `WsState` | 可訂閱 store 的 state 形狀(連線健康/佇列/重連) |
|
|
321
330
|
|
|
322
331
|
---
|
|
323
332
|
|
|
@@ -337,15 +346,15 @@ import {
|
|
|
337
346
|
} from "react-ws-context/stall";
|
|
338
347
|
```
|
|
339
348
|
|
|
340
|
-
| 匯出 | 說明
|
|
341
|
-
| ---------------------------- |
|
|
342
|
-
| `STALL_MESSAGE_TYPE` | 客戶端控制訊息 type 常數(`"STALL"`)
|
|
343
|
-
| `STALL_ACK_TYPE` | 伺服器確認 type 常數(`"STALL_ACK"
|
|
344
|
-
| `createStallMessage(action)` | 建立可 `sendJson`
|
|
345
|
-
| `parseStallMessage(data)` | 從 `useWsEvents("message")` 的 `data`
|
|
346
|
-
| `StallAction` | `"stall" \| "release"`
|
|
347
|
-
| `StallMessage` | `{ type: "STALL"; action: StallAction }`
|
|
348
|
-
| `StallAck` | `{ type: "STALL_ACK"; action: StallAction; active: boolean }`
|
|
349
|
+
| 匯出 | 說明 |
|
|
350
|
+
| ---------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
351
|
+
| `STALL_MESSAGE_TYPE` | 客戶端控制訊息 type 常數(`"STALL"`) |
|
|
352
|
+
| `STALL_ACK_TYPE` | 伺服器確認 type 常數(`"STALL_ACK"`)— 僅供型別使用,無內建 parser |
|
|
353
|
+
| `createStallMessage(action)` | 建立可 `sendJson` 的客戶端 `STALL` 訊息 |
|
|
354
|
+
| `parseStallMessage(data)` | 從 `useWsEvents("message")` 的 `data` 解析客戶端 `STALL` 訊息;格式不符回傳 `null`(不含 `STALL_ACK`) |
|
|
355
|
+
| `StallAction` | `"stall" \| "release"` |
|
|
356
|
+
| `StallMessage` | `{ type: "STALL"; action: StallAction }` |
|
|
357
|
+
| `StallAck` | `{ type: "STALL_ACK"; action: StallAction; active: boolean }` — 伺服器 ack 請自行解析 |
|
|
349
358
|
|
|
350
359
|
**範例:**
|
|
351
360
|
|
|
@@ -364,14 +373,15 @@ sendJson(createStallMessage("stall"));
|
|
|
364
373
|
|
|
365
374
|
## 設計取捨與限制
|
|
366
375
|
|
|
367
|
-
| 項目 | 說明
|
|
368
|
-
| -------------- |
|
|
369
|
-
| 設定不可變 | `url`、`reconnectMs`
|
|
370
|
-
| 重連策略 | 固定間隔,無 exponential backoff;`reconnectMax > 0` 可限制次數
|
|
371
|
-
| SSR | 不在 server 建立 `WebSocket`;`connect()` 在 `window` 不存在時為 no-op
|
|
372
|
-
| 錯誤狀態 | 不設 `"error"` status;請監聽 `useWsEvents("error")`
|
|
373
|
-
| `WsState` 範圍 | 只含連線健康/佇列/重連;訊息與業務資料不走 store
|
|
374
|
-
| 訊息與渲染 | 只呼叫 `useWsActions` 的元件不會因 store 或 message 重繪
|
|
376
|
+
| 項目 | 說明 |
|
|
377
|
+
| -------------- | ------------------------------------------------------------------------ |
|
|
378
|
+
| 設定不可變 | `url`、`reconnectMs` 等建立後固定;要換 URL 請另建一組 `createWsContext` |
|
|
379
|
+
| 重連策略 | 固定間隔,無 exponential backoff;`reconnectMax > 0` 可限制次數 |
|
|
380
|
+
| SSR | 不在 server 建立 `WebSocket`;`connect()` 在 `window` 不存在時為 no-op |
|
|
381
|
+
| 錯誤狀態 | 不設 `"error"` status;請監聽 `useWsEvents("error")` |
|
|
382
|
+
| `WsState` 範圍 | 只含連線健康/佇列/重連;訊息與業務資料不走 store |
|
|
383
|
+
| 訊息與渲染 | 只呼叫 `useWsActions` 的元件不會因 store 或 message 重繪 |
|
|
384
|
+
| Store 更新 | 相同欄位值重複寫入不觸發訂閱;建議以 selector 訂閱 |
|
|
375
385
|
|
|
376
386
|
---
|
|
377
387
|
|
|
@@ -390,8 +400,8 @@ sendJson(createStallMessage("stall"));
|
|
|
390
400
|
- **作者/維護:** [pmndrs](https://github.com/pmndrs)(Poimandres)
|
|
391
401
|
- **授權:** [MIT](https://github.com/pmndrs/zustand/blob/main/LICENSE)
|
|
392
402
|
- **借鑑範圍:**
|
|
393
|
-
- 外部 store(`getState` / `setState` / `subscribe` / `getInitialState`)— 靈感與行為對齊 [`vanilla.ts`](https://github.com/pmndrs/zustand/blob/main/src/vanilla.ts),非完整搬移(無 middleware、replace、initializer factory
|
|
394
|
-
- React 訂閱 hook — 靈感來自 [`react.ts`](https://github.com/pmndrs/zustand/blob/main/src/react.ts) 的 `useStore
|
|
403
|
+
- 外部 store(`getState` / `setState` / `subscribe` / `getInitialState`)— 靈感與行為對齊 [`vanilla.ts`](https://github.com/pmndrs/zustand/blob/main/src/vanilla.ts),非完整搬移(無 middleware、replace、initializer factory);`setState` 另含 partial shallow dedup(值未變不通知)
|
|
404
|
+
- React 訂閱 hook — 靈感來自 [`react.ts`](https://github.com/pmndrs/zustand/blob/main/src/react.ts) 的 `useStore`(無 `useDebugValue`);公開 API 的可選 selector overload 在 `createUseWsStore`
|
|
395
405
|
- **對應原始碼:** `src/ws-context/store.ts`、`src/ws-context/use-store.ts`
|
|
396
406
|
|
|
397
407
|
### [nanoevents](https://github.com/ai/nanoevents)
|
|
@@ -400,5 +410,5 @@ sendJson(createStallMessage("stall"));
|
|
|
400
410
|
- **授權:** [MIT](https://github.com/ai/nanoevents/blob/main/LICENSE)
|
|
401
411
|
- **借鑑範圍:**
|
|
402
412
|
- Typed event emitter — 執行期邏輯幾乎對齊 [`createNanoEvents`](https://github.com/ai/nanoevents/blob/main/index.js);型別為本套件收斂版
|
|
403
|
-
-
|
|
404
|
-
- **對應原始碼:** `src/ws-context/emitter.ts`
|
|
413
|
+
- React 訂閱包裝 — 本套件自行新增(`ws-events.ts`)
|
|
414
|
+
- **對應原始碼:** `src/ws-context/emitter.ts`、`src/ws-context/ws-events.ts`
|
package/dist/index.d.mts
CHANGED
|
@@ -54,15 +54,15 @@ type WsState = {
|
|
|
54
54
|
};
|
|
55
55
|
//#endregion
|
|
56
56
|
//#region src/ws-context/liveness/types.d.ts
|
|
57
|
-
/**
|
|
57
|
+
/** 探活設定 */
|
|
58
58
|
interface LivenessOptions {
|
|
59
|
-
/**
|
|
59
|
+
/** ping 間隔(毫秒) */
|
|
60
60
|
intervalMs: number;
|
|
61
|
-
/**
|
|
61
|
+
/** 等待 pong 逾時(毫秒) */
|
|
62
62
|
timeoutMs: number;
|
|
63
|
-
/**
|
|
63
|
+
/** ping 內容;函式則每次動態產生 */
|
|
64
64
|
ping: unknown | (() => unknown);
|
|
65
|
-
/**
|
|
65
|
+
/** 判定傳入資料是否為 pong */
|
|
66
66
|
isPong: (data: unknown) => boolean;
|
|
67
67
|
}
|
|
68
68
|
//#endregion
|
|
@@ -74,77 +74,78 @@ interface CreateWsContextOptions {
|
|
|
74
74
|
/** 連線協定 */
|
|
75
75
|
protocols?: string | string[];
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
77
|
+
* 是否在 WsProvider 載入時自動連線。
|
|
78
78
|
*
|
|
79
|
-
*
|
|
79
|
+
* @default true
|
|
80
80
|
*/
|
|
81
81
|
autoConnect?: boolean;
|
|
82
82
|
/**
|
|
83
|
-
*
|
|
83
|
+
* 非主動斷線後,自動重連的間隔(毫秒)。
|
|
84
|
+
*
|
|
85
|
+
* `0` 表示不重連。
|
|
84
86
|
*
|
|
85
87
|
* @default 0
|
|
86
88
|
*/
|
|
87
89
|
reconnectMs?: number;
|
|
88
90
|
/**
|
|
89
|
-
*
|
|
90
|
-
* `reconnectAttempt` 於成功 `open`、手動 `connect()` 或 `disconnect()` 歸零。
|
|
91
|
+
* 非主動斷線後,最多自動重連幾次。
|
|
91
92
|
*
|
|
92
|
-
* `0`
|
|
93
|
+
* `0` 表示不限制;需搭配 `reconnectMs > 0` 才會重連。
|
|
93
94
|
*
|
|
94
95
|
* @default 0
|
|
95
96
|
*/
|
|
96
97
|
reconnectMax?: number;
|
|
97
98
|
/**
|
|
98
|
-
*
|
|
99
|
+
* 未連線時,待送訊息的佇列上限。
|
|
100
|
+
*
|
|
101
|
+
* `0` 表示關閉佇列。
|
|
99
102
|
*
|
|
100
103
|
* @default 0
|
|
101
104
|
*/
|
|
102
105
|
outgoingQueueMax?: number;
|
|
103
106
|
/**
|
|
104
|
-
*
|
|
107
|
+
* 將原始 `MessageEvent.data` 轉成業務資料。
|
|
105
108
|
*
|
|
106
|
-
*
|
|
109
|
+
* 預設:字串嘗試 `JSON.parse`,失敗則原樣回傳;非字串原樣回傳。
|
|
107
110
|
*/
|
|
108
111
|
parse?: (data: MessageEvent["data"]) => unknown;
|
|
109
|
-
/**
|
|
112
|
+
/** 探活設定;省略則不啟用 */
|
|
110
113
|
liveness?: LivenessOptions;
|
|
111
114
|
}
|
|
112
115
|
interface WsEvents {
|
|
113
116
|
/**
|
|
114
117
|
* 收到訊息
|
|
115
118
|
*
|
|
116
|
-
* @param data
|
|
117
|
-
* @param event
|
|
119
|
+
* @param data 經 `parse` 處理後的資料
|
|
120
|
+
* @param event 原始 `MessageEvent`
|
|
118
121
|
*/
|
|
119
122
|
message: (data: unknown, event: MessageEvent) => void;
|
|
120
123
|
/** 連線建立 */
|
|
121
124
|
open: (event: Event) => void;
|
|
122
|
-
/**
|
|
125
|
+
/** 連線錯誤 */
|
|
123
126
|
error: (event: Event) => void;
|
|
124
|
-
/**
|
|
127
|
+
/** 連線關閉 */
|
|
125
128
|
close: (event: CloseEvent) => void;
|
|
126
129
|
}
|
|
127
|
-
/** 連線操作 API
|
|
130
|
+
/** 連線操作 API;連線層 state 請用 `useWsStore` 訂閱 */
|
|
128
131
|
interface WsContextValue {
|
|
129
132
|
/**
|
|
130
|
-
*
|
|
133
|
+
* 傳送原始資料。
|
|
131
134
|
*
|
|
132
|
-
* @
|
|
133
|
-
* @returns 是否已送出或已入隊
|
|
135
|
+
* @returns `true` 表示已送出或已入隊;`false` 表示未送出
|
|
134
136
|
*/
|
|
135
137
|
send: (data: Parameters<WebSocket["send"]>[0]) => boolean;
|
|
136
138
|
/**
|
|
137
|
-
*
|
|
139
|
+
* 以 JSON 傳送資料。
|
|
138
140
|
*
|
|
139
|
-
* @
|
|
140
|
-
* @returns 是否已送出或已入隊
|
|
141
|
+
* @returns 同 `send`;無法序列化時為 `false`
|
|
141
142
|
*/
|
|
142
143
|
sendJson: (data: unknown) => boolean;
|
|
143
144
|
/** 建立連線 */
|
|
144
145
|
connect: () => void;
|
|
145
|
-
/**
|
|
146
|
+
/** 主動斷開連線 */
|
|
146
147
|
disconnect: () => void;
|
|
147
|
-
/** 讀取當下 `status
|
|
148
|
+
/** 讀取當下 `status`;不訂閱、不觸發渲染 */
|
|
148
149
|
getStatus: () => WsStatus;
|
|
149
150
|
}
|
|
150
151
|
//#endregion
|
|
@@ -166,5 +167,5 @@ declare function createWsContext(options: CreateWsContextOptions): {
|
|
|
166
167
|
useWsEvents: <E extends keyof WsEvents>(type: E, handler: WsEvents[E]) => void;
|
|
167
168
|
};
|
|
168
169
|
//#endregion
|
|
169
|
-
export { type CreateWsContextOptions, type WsContextValue, type WsEvents, type WsPhase, type WsState, type WsStatus, createWsContext };
|
|
170
|
+
export { type CreateWsContextOptions, type LivenessOptions, type WsContextValue, type WsEvents, type WsPhase, type WsState, type WsStatus, createWsContext };
|
|
170
171
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/ws-context/ws-store.ts","../src/ws-context/liveness/types.ts","../src/ws-context/types.ts","../src/ws-context/index.tsx"],"mappings":";;;;;;;;;;;;KAcY;;;;;;;;;;;;KAaA;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/ws-context/ws-store.ts","../src/ws-context/liveness/types.ts","../src/ws-context/types.ts","../src/ws-context/index.tsx"],"mappings":";;;;;;;;;;;;KAcY;;;;;;;;;;;;KAaA;;;;;;;;;;KAYA;;EAEV,QAAQ;;EAER,OAAO;;;;;;;;EAQP;;;;;;EAMA;;;;;UCxDe;;EAEf;;EAEA;;EAEA;;EAEA,SAAS;;;;;UCLM;;EAEf;;EAEA;;;;;;EAMA;;;;;;;;EAQA;;;;;;;;EAQA;;;;;;;;EAQA;;;;;;EAMA,SAAS,MAAM;;EAEf,WAAW;;UAGI;;;;;;;EAOf,UAAU,eAAe,OAAO;;EAEhC,OAAO,OAAO;;EAEd,QAAQ,OAAO;;EAEf,QAAQ,OAAO;;;UAIA;;;;;;EAMf,OAAO,MAAM,WAAW;;;;;;EAMxB,WAAW;;EAEX;;EAEA;;EAEA,iBAAiB;;;;;;;;;;;iBCxCH,gBAAgB,SAAS;EAmBL,eAAA,YAAA,sCAAiB,IAAA"}
|