ly-utils-lib 1.0.12 → 2.5.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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1002 -685
  3. package/dist/array.cjs +237 -0
  4. package/dist/array.cjs.map +1 -0
  5. package/dist/array.d.cts +2 -0
  6. package/dist/array.d.ts +2 -0
  7. package/dist/array.js +150 -0
  8. package/dist/array.js.map +1 -0
  9. package/dist/crypto.cjs +193 -0
  10. package/dist/crypto.cjs.map +1 -0
  11. package/dist/crypto.d.cts +3 -0
  12. package/dist/crypto.d.ts +3 -0
  13. package/dist/crypto.js +144 -0
  14. package/dist/crypto.js.map +1 -0
  15. package/dist/date.cjs +563 -0
  16. package/dist/date.cjs.map +1 -0
  17. package/dist/date.d.cts +2 -0
  18. package/dist/date.d.ts +2 -0
  19. package/dist/date.js +451 -0
  20. package/dist/date.js.map +1 -0
  21. package/dist/excel.cjs +227 -0
  22. package/dist/excel.cjs.map +1 -0
  23. package/dist/excel.d.cts +2 -0
  24. package/dist/excel.d.ts +2 -0
  25. package/dist/excel.js +196 -0
  26. package/dist/excel.js.map +1 -0
  27. package/dist/index-B80SEVzM.d.cts +382 -0
  28. package/dist/index-B80SEVzM.d.ts +382 -0
  29. package/dist/index-Ba1rjTzj.d.cts +299 -0
  30. package/dist/index-Ba1rjTzj.d.ts +299 -0
  31. package/dist/index-Bg1ise7y.d.cts +253 -0
  32. package/dist/index-Bg1ise7y.d.ts +253 -0
  33. package/dist/index-BoqNpwNa.d.cts +203 -0
  34. package/dist/index-BoqNpwNa.d.ts +203 -0
  35. package/dist/index-C0qUnb9Y.d.cts +533 -0
  36. package/dist/index-C0qUnb9Y.d.ts +533 -0
  37. package/dist/index-Cq1GhjpY.d.cts +229 -0
  38. package/dist/index-Cq1GhjpY.d.ts +229 -0
  39. package/dist/index-Cy-mb5v_.d.cts +262 -0
  40. package/dist/index-Cy-mb5v_.d.ts +262 -0
  41. package/dist/index-D1f9Sym2.d.cts +148 -0
  42. package/dist/index-D1f9Sym2.d.ts +148 -0
  43. package/dist/index-Dan5oF-5.d.cts +213 -0
  44. package/dist/index-Dan5oF-5.d.ts +213 -0
  45. package/dist/index-XABfrs7z.d.cts +596 -0
  46. package/dist/index-XABfrs7z.d.ts +596 -0
  47. package/dist/index-YXWfKCK7.d.cts +109 -0
  48. package/dist/index-YXWfKCK7.d.ts +109 -0
  49. package/dist/index.cjs +3691 -0
  50. package/dist/index.cjs.map +1 -0
  51. package/dist/index.d.cts +22 -0
  52. package/dist/index.d.ts +22 -0
  53. package/dist/index.js +3629 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/map.cjs +839 -0
  56. package/dist/map.cjs.map +1 -0
  57. package/dist/map.d.cts +6 -0
  58. package/dist/map.d.ts +6 -0
  59. package/dist/map.js +811 -0
  60. package/dist/map.js.map +1 -0
  61. package/dist/object.cjs +316 -0
  62. package/dist/object.cjs.map +1 -0
  63. package/dist/object.d.cts +2 -0
  64. package/dist/object.d.ts +2 -0
  65. package/dist/object.js +247 -0
  66. package/dist/object.js.map +1 -0
  67. package/dist/pdf.cjs +197 -0
  68. package/dist/pdf.cjs.map +1 -0
  69. package/dist/pdf.d.cts +3 -0
  70. package/dist/pdf.d.ts +3 -0
  71. package/dist/pdf.js +173 -0
  72. package/dist/pdf.js.map +1 -0
  73. package/dist/storage.cjs +255 -0
  74. package/dist/storage.cjs.map +1 -0
  75. package/dist/storage.d.cts +1 -0
  76. package/dist/storage.d.ts +1 -0
  77. package/dist/storage.js +226 -0
  78. package/dist/storage.js.map +1 -0
  79. package/dist/string.cjs +232 -0
  80. package/dist/string.cjs.map +1 -0
  81. package/dist/string.d.cts +2 -0
  82. package/dist/string.d.ts +2 -0
  83. package/dist/string.js +170 -0
  84. package/dist/string.js.map +1 -0
  85. package/dist/utils.cjs +429 -0
  86. package/dist/utils.cjs.map +1 -0
  87. package/dist/utils.d.cts +2 -0
  88. package/dist/utils.d.ts +2 -0
  89. package/dist/utils.js +371 -0
  90. package/dist/utils.js.map +1 -0
  91. package/dist/websocket.cjs +338 -0
  92. package/dist/websocket.cjs.map +1 -0
  93. package/dist/websocket.d.cts +1 -0
  94. package/dist/websocket.d.ts +1 -0
  95. package/dist/websocket.js +330 -0
  96. package/dist/websocket.js.map +1 -0
  97. package/package.json +159 -33
  98. package/dist/ly-utils-lib.cjs.js +0 -115
  99. package/dist/ly-utils-lib.cjs.js.map +0 -1
  100. package/dist/ly-utils-lib.es.js +0 -58589
  101. package/dist/ly-utils-lib.es.js.map +0 -1
  102. package/dist/ly-utils-lib.umd.js +0 -115
  103. package/dist/ly-utils-lib.umd.js.map +0 -1
  104. package/dist/types/index.d.ts +0 -15
  105. package/dist/types/utils/esToolkit.d.ts +0 -2
  106. package/dist/types/utils/ol.d.ts +0 -175
  107. package/dist/types/utils/router.d.ts +0 -10
  108. package/dist/types/utils/storage.d.ts +0 -42
  109. package/dist/types/utils/time.d.ts +0 -66
  110. package/dist/types/utils/tool.d.ts +0 -80
  111. package/dist/vite.svg +0 -1
@@ -0,0 +1,338 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ // src/modules/websocket/index.ts
6
+ var WebSocketState = /* @__PURE__ */ ((WebSocketState2) => {
7
+ WebSocketState2[WebSocketState2["CONNECTING"] = 0] = "CONNECTING";
8
+ WebSocketState2[WebSocketState2["OPEN"] = 1] = "OPEN";
9
+ WebSocketState2[WebSocketState2["CLOSING"] = 2] = "CLOSING";
10
+ WebSocketState2[WebSocketState2["CLOSED"] = 3] = "CLOSED";
11
+ return WebSocketState2;
12
+ })(WebSocketState || {});
13
+ var WebSocketClient = class {
14
+ constructor(options) {
15
+ this.ws = null;
16
+ this.handlers = {};
17
+ this.reconnectTimer = null;
18
+ this.heartbeatTimer = null;
19
+ this.heartbeatTimeoutTimer = null;
20
+ this.reconnectCount = 0;
21
+ this.isManualDisconnect = false;
22
+ this.messageQueue = [];
23
+ this.connectResolve = null;
24
+ this.connectReject = null;
25
+ this.options = {
26
+ url: options.url,
27
+ protocol: options.protocol || (options.url.startsWith("https") ? "wss" : "ws"),
28
+ protocols: options.protocols || [],
29
+ autoReconnect: options.autoReconnect ?? true,
30
+ reconnectAttempts: options.reconnectAttempts ?? 3,
31
+ reconnectInterval: options.reconnectInterval ?? 3e3,
32
+ heartbeatInterval: options.heartbeatInterval ?? 3e4,
33
+ heartbeatMessage: options.heartbeatMessage ?? "ping",
34
+ heartbeatTimeout: options.heartbeatTimeout ?? 5e3,
35
+ connectTimeout: options.connectTimeout ?? 1e4,
36
+ debug: options.debug ?? true
37
+ };
38
+ if (options.autoReconnect !== false) {
39
+ this.connect();
40
+ }
41
+ }
42
+ /**
43
+ * 连接 WebSocket
44
+ */
45
+ connect() {
46
+ if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
47
+ this.log("WebSocket already connected or connecting");
48
+ return;
49
+ }
50
+ this.isManualDisconnect = false;
51
+ this.reconnectCount = 0;
52
+ const protocol = this.options.url.startsWith("ws://") || this.options.url.startsWith("wss://") ? "" : `${this.options.protocol}://`;
53
+ const wsUrl = protocol ? `${protocol}${this.options.url}` : this.options.url;
54
+ this.log(`Connecting to ${wsUrl}`);
55
+ try {
56
+ this.ws = new WebSocket(wsUrl, this.options.protocols);
57
+ this.setupEventHandlers();
58
+ setTimeout(() => {
59
+ if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {
60
+ this.ws.close();
61
+ this.log("Connection timeout");
62
+ if (this.connectReject) {
63
+ this.connectReject(new Error("Connection timeout"));
64
+ this.connectResolve = null;
65
+ this.connectReject = null;
66
+ }
67
+ }
68
+ }, this.options.connectTimeout);
69
+ } catch (error) {
70
+ this.log("Connection failed:", error);
71
+ this.handleError(error);
72
+ }
73
+ }
74
+ /**
75
+ * 断开连接
76
+ */
77
+ disconnect() {
78
+ this.isManualDisconnect = true;
79
+ this.cleanup();
80
+ if (this.ws) {
81
+ this.ws.close();
82
+ this.ws = null;
83
+ }
84
+ this.log("Disconnected manually");
85
+ }
86
+ /**
87
+ * 发送消息(异步)
88
+ */
89
+ async send(data) {
90
+ if (!this.isConnected()) {
91
+ return new Promise((resolve, reject) => {
92
+ this.messageQueue.push(data);
93
+ const checkConnection = () => {
94
+ if (this.isConnected()) {
95
+ this.sendSync(data);
96
+ resolve();
97
+ } else if (!this.ws) {
98
+ reject(new Error("WebSocket is not connected"));
99
+ } else {
100
+ setTimeout(checkConnection, 100);
101
+ }
102
+ };
103
+ checkConnection();
104
+ });
105
+ }
106
+ this.sendSync(data);
107
+ }
108
+ /**
109
+ * 发送消息(同步)
110
+ */
111
+ sendSync(data) {
112
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
113
+ this.log("WebSocket is not connected, message queued");
114
+ this.messageQueue.push(data);
115
+ return;
116
+ }
117
+ try {
118
+ const message = typeof data === "object" ? JSON.stringify(data) : data;
119
+ this.ws.send(message);
120
+ this.log("Message sent:", message);
121
+ } catch (error) {
122
+ this.log("Send error:", error);
123
+ this.handleError(error);
124
+ }
125
+ }
126
+ /**
127
+ * 获取连接状态
128
+ */
129
+ getState() {
130
+ return this.ws?.readyState ?? 3 /* CLOSED */;
131
+ }
132
+ /**
133
+ * 是否已连接
134
+ */
135
+ isConnected() {
136
+ return this.ws?.readyState === WebSocket.OPEN;
137
+ }
138
+ /**
139
+ * 获取 WebSocket 实例
140
+ */
141
+ getInstance() {
142
+ return this.ws;
143
+ }
144
+ /**
145
+ * 设置事件处理器
146
+ */
147
+ on(event, handler) {
148
+ this.handlers[event] = handler;
149
+ }
150
+ /**
151
+ * 移除事件处理器
152
+ */
153
+ off(event, handler) {
154
+ if (!handler || this.handlers[event] === handler) {
155
+ delete this.handlers[event];
156
+ }
157
+ }
158
+ /**
159
+ * 重新连接
160
+ */
161
+ reconnect() {
162
+ this.disconnect();
163
+ this.reconnectCount = 0;
164
+ this.isManualDisconnect = false;
165
+ this.connect();
166
+ }
167
+ /**
168
+ * 设置事件处理器
169
+ */
170
+ setupEventHandlers() {
171
+ if (!this.ws) return;
172
+ this.ws.onopen = (event) => {
173
+ this.log("Connected");
174
+ this.reconnectCount = 0;
175
+ while (this.messageQueue.length > 0) {
176
+ const message = this.messageQueue.shift();
177
+ if (message) {
178
+ this.sendSync(message);
179
+ }
180
+ }
181
+ this.startHeartbeat();
182
+ if (this.handlers.onOpen) {
183
+ this.handlers.onOpen(event);
184
+ }
185
+ if (this.connectResolve) {
186
+ this.connectResolve();
187
+ this.connectResolve = null;
188
+ this.connectReject = null;
189
+ }
190
+ };
191
+ this.ws.onmessage = (event) => {
192
+ this.log("Message received:", event.data);
193
+ let data = event.data;
194
+ if (typeof event.data === "string") {
195
+ try {
196
+ data = JSON.parse(event.data);
197
+ } catch {
198
+ }
199
+ }
200
+ if (this.handlers.onMessage) {
201
+ this.handlers.onMessage(data, event);
202
+ }
203
+ };
204
+ this.ws.onclose = (event) => {
205
+ this.log("Connection closed:", event.code, event.reason);
206
+ this.cleanup();
207
+ if (this.handlers.onClose) {
208
+ this.handlers.onClose(event);
209
+ }
210
+ if (!this.isManualDisconnect && this.options.autoReconnect) {
211
+ this.attemptReconnect();
212
+ }
213
+ };
214
+ this.ws.onerror = (event) => {
215
+ this.log("Error:", event);
216
+ if (this.handlers.onError) {
217
+ this.handlers.onError(event);
218
+ }
219
+ };
220
+ }
221
+ /**
222
+ * 尝试重连
223
+ */
224
+ attemptReconnect() {
225
+ if (this.reconnectCount >= this.options.reconnectAttempts) {
226
+ this.log("Reconnect failed, max attempts reached");
227
+ this.cleanup();
228
+ if (this.handlers.onReconnectFailed) {
229
+ this.handlers.onReconnectFailed();
230
+ }
231
+ if (this.connectReject) {
232
+ this.connectReject(new Error("Reconnect failed"));
233
+ this.connectResolve = null;
234
+ this.connectReject = null;
235
+ }
236
+ return;
237
+ }
238
+ this.reconnectCount++;
239
+ this.log(`Reconnecting... Attempt ${this.reconnectCount}/${this.options.reconnectAttempts}`);
240
+ if (this.handlers.onReconnect) {
241
+ this.handlers.onReconnect(this.reconnectCount);
242
+ }
243
+ this.reconnectTimer = setTimeout(() => {
244
+ this.connect();
245
+ }, this.options.reconnectInterval);
246
+ }
247
+ /**
248
+ * 启动心跳
249
+ */
250
+ startHeartbeat() {
251
+ this.stopHeartbeat();
252
+ this.heartbeatTimer = setInterval(() => {
253
+ if (this.isConnected()) {
254
+ const message = this.options.heartbeatMessage;
255
+ this.log("Sending heartbeat");
256
+ if (this.handlers.onHeartbeat) {
257
+ this.handlers.onHeartbeat();
258
+ }
259
+ this.sendSync(message);
260
+ this.heartbeatTimeoutTimer = setTimeout(() => {
261
+ this.log("Heartbeat timeout");
262
+ if (this.handlers.onHeartbeatTimeout) {
263
+ this.handlers.onHeartbeatTimeout();
264
+ }
265
+ if (this.ws) {
266
+ this.ws.close();
267
+ }
268
+ }, this.options.heartbeatTimeout);
269
+ }
270
+ }, this.options.heartbeatInterval);
271
+ }
272
+ /**
273
+ * 停止心跳
274
+ */
275
+ stopHeartbeat() {
276
+ if (this.heartbeatTimer) {
277
+ clearInterval(this.heartbeatTimer);
278
+ this.heartbeatTimer = null;
279
+ }
280
+ if (this.heartbeatTimeoutTimer) {
281
+ clearTimeout(this.heartbeatTimeoutTimer);
282
+ this.heartbeatTimeoutTimer = null;
283
+ }
284
+ }
285
+ /**
286
+ * 清理资源
287
+ */
288
+ cleanup() {
289
+ this.stopHeartbeat();
290
+ if (this.reconnectTimer) {
291
+ clearTimeout(this.reconnectTimer);
292
+ this.reconnectTimer = null;
293
+ }
294
+ }
295
+ /**
296
+ * 处理错误
297
+ */
298
+ handleError(error) {
299
+ this.log("Error:", error.message);
300
+ if (this.handlers.onError) {
301
+ this.handlers.onError(new ErrorEvent("error", { error }));
302
+ }
303
+ }
304
+ /**
305
+ * 日志输出
306
+ */
307
+ log(...args) {
308
+ if (this.options.debug) {
309
+ console.log("[WebSocket]", ...args);
310
+ }
311
+ }
312
+ };
313
+ function createWebSocket(options) {
314
+ return new WebSocketClient(options);
315
+ }
316
+ function quickConnect(url, handlers) {
317
+ const client = new WebSocketClient({ url, autoReconnect: true });
318
+ if (handlers) {
319
+ Object.entries(handlers).forEach(([event, handler]) => {
320
+ client.on(event, handler);
321
+ });
322
+ }
323
+ return client;
324
+ }
325
+ var websocket_default = {
326
+ WebSocketClient,
327
+ createWebSocket,
328
+ quickConnect,
329
+ WebSocketState
330
+ };
331
+
332
+ exports.WebSocketClient = WebSocketClient;
333
+ exports.WebSocketState = WebSocketState;
334
+ exports.createWebSocket = createWebSocket;
335
+ exports.default = websocket_default;
336
+ exports.quickConnect = quickConnect;
337
+ //# sourceMappingURL=websocket.cjs.map
338
+ //# sourceMappingURL=websocket.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/modules/websocket/index.ts"],"names":["WebSocketState"],"mappings":"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","file":"websocket.cjs","sourcesContent":["/**\n * WebSocket Module - WebSocket 工具\n *\n * 提供简化的 WebSocket 连接、消息发送、心跳检测和重连机制\n */\n\n// ==================== 类型定义 ====================\n\n/**\n * WebSocket 连接状态\n */\nexport enum WebSocketState {\n CONNECTING = 0,\n OPEN = 1,\n CLOSING = 2,\n CLOSED = 3,\n}\n\n/**\n * WebSocket 配置选项\n */\nexport interface WebSocketOptions {\n /** WebSocket 服务器地址 */\n url: string\n /** 协议(wss:// 或 ws://),默认自动检测 */\n protocol?: 'ws' | 'wss'\n /** 子协议 */\n protocols?: string | string[]\n /** 是否自动重连,默认 true */\n autoReconnect?: boolean\n /** 重连次数,默认 3 */\n reconnectAttempts?: number\n /** 重连间隔(毫秒),默认 3000 */\n reconnectInterval?: number\n /** 心跳检测间隔(毫秒),默认 30000 */\n heartbeatInterval?: number\n /** 心跳消息内容,默认 'ping' */\n heartbeatMessage?: string | object\n /** 心跳超时时间(毫秒),默认 5000 */\n heartbeatTimeout?: number\n /** 连接超时时间(毫秒),默认 10000 */\n connectTimeout?: number\n /** 是否记录日志,默认 true */\n debug?: boolean\n}\n\n/**\n * WebSocket 消息类型\n */\nexport type WebSocketMessage = string | object | ArrayBuffer | Blob\n\n/**\n * WebSocket 事件处理器\n */\nexport interface WebSocketEventHandlers {\n /** 连接成功回调 */\n onOpen?: (event: Event) => void\n /** 接收消息回调 */\n onMessage?: (data: WebSocketMessage, event: MessageEvent) => void\n /** 连接关闭回调 */\n onClose?: (event: CloseEvent) => void\n /** 错误回调 */\n onError?: (event: Event) => void\n /** 重连开始回调 */\n onReconnect?: (attempt: number) => void\n /** 重连成功回调 */\n onReconnectSuccess?: (attempt: number) => void\n /** 重连失败回调 */\n onReconnectFailed?: () => void\n /** 心跳回调 */\n onHeartbeat?: () => void\n /** 心跳超时回调 */\n onHeartbeatTimeout?: () => void\n}\n\n/**\n * WebSocket 实例接口\n */\nexport interface IWebSocketClient {\n /** 连接 WebSocket */\n connect(): void\n /** 断开连接 */\n disconnect(): void\n /** 发送消息 */\n send(data: WebSocketMessage): Promise<void>\n /** 发送消息(不带 Promise) */\n sendSync(data: WebSocketMessage): void\n /** 获取连接状态 */\n getState(): WebSocketState\n /** 是否已连接 */\n isConnected(): boolean\n /** 获取 WebSocket 实例 */\n getInstance(): WebSocket | null\n /** 设置事件处理器 */\n on<K extends keyof WebSocketEventHandlers>(\n event: K,\n handler: WebSocketEventHandlers[K]\n ): void\n /** 移除事件处理器 */\n off<K extends keyof WebSocketEventHandlers>(\n event: K,\n handler?: WebSocketEventHandlers[K]\n ): void\n /** 重新连接 */\n reconnect(): void\n}\n\n// ==================== WebSocket 客户端类 ====================\n\n/**\n * WebSocket 客户端类\n */\nexport class WebSocketClient implements IWebSocketClient {\n private ws: WebSocket | null = null\n private options: Required<Omit<WebSocketOptions, 'protocols' | 'debug'>> &\n Pick<WebSocketOptions, 'protocols' | 'debug'>\n private handlers: WebSocketEventHandlers = {}\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null\n private heartbeatTimeoutTimer: ReturnType<typeof setTimeout> | null = null\n private reconnectCount = 0\n private isManualDisconnect = false\n private messageQueue: WebSocketMessage[] = []\n private connectResolve: (() => void) | null = null\n private connectReject: ((error: Error) => void) | null = null\n\n constructor(options: WebSocketOptions) {\n this.options = {\n url: options.url,\n protocol: options.protocol || (options.url.startsWith('https') ? 'wss' : 'ws'),\n protocols: options.protocols || [],\n autoReconnect: options.autoReconnect ?? true,\n reconnectAttempts: options.reconnectAttempts ?? 3,\n reconnectInterval: options.reconnectInterval ?? 3000,\n heartbeatInterval: options.heartbeatInterval ?? 30000,\n heartbeatMessage: options.heartbeatMessage ?? 'ping',\n heartbeatTimeout: options.heartbeatTimeout ?? 5000,\n connectTimeout: options.connectTimeout ?? 10000,\n debug: options.debug ?? true,\n }\n\n // 自动连接\n if (options.autoReconnect !== false) {\n this.connect()\n }\n }\n\n /**\n * 连接 WebSocket\n */\n connect(): void {\n if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {\n this.log('WebSocket already connected or connecting')\n return\n }\n\n this.isManualDisconnect = false\n this.reconnectCount = 0\n\n const protocol = this.options.url.startsWith('ws://') || this.options.url.startsWith('wss://')\n ? ''\n : `${this.options.protocol}://`\n\n const wsUrl = protocol ? `${protocol}${this.options.url}` : this.options.url\n\n this.log(`Connecting to ${wsUrl}`)\n\n try {\n this.ws = new WebSocket(wsUrl, this.options.protocols)\n\n this.setupEventHandlers()\n\n // 设置连接超时\n setTimeout(() => {\n if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {\n this.ws.close()\n this.log('Connection timeout')\n if (this.connectReject) {\n this.connectReject(new Error('Connection timeout'))\n this.connectResolve = null\n this.connectReject = null\n }\n }\n }, this.options.connectTimeout)\n } catch (error) {\n this.log('Connection failed:', error)\n this.handleError(error as Error)\n }\n }\n\n /**\n * 断开连接\n */\n disconnect(): void {\n this.isManualDisconnect = true\n this.cleanup()\n\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n\n this.log('Disconnected manually')\n }\n\n /**\n * 发送消息(异步)\n */\n async send(data: WebSocketMessage): Promise<void> {\n if (!this.isConnected()) {\n return new Promise((resolve, reject) => {\n this.messageQueue.push(data)\n const checkConnection = () => {\n if (this.isConnected()) {\n this.sendSync(data)\n resolve()\n } else if (!this.ws) {\n reject(new Error('WebSocket is not connected'))\n } else {\n setTimeout(checkConnection, 100)\n }\n }\n checkConnection()\n })\n }\n\n this.sendSync(data)\n }\n\n /**\n * 发送消息(同步)\n */\n sendSync(data: WebSocketMessage): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.log('WebSocket is not connected, message queued')\n this.messageQueue.push(data)\n return\n }\n\n try {\n const message = typeof data === 'object' ? JSON.stringify(data) : data\n this.ws.send(message)\n this.log('Message sent:', message)\n } catch (error) {\n this.log('Send error:', error)\n this.handleError(error as Error)\n }\n }\n\n /**\n * 获取连接状态\n */\n getState(): WebSocketState {\n return this.ws?.readyState ?? WebSocketState.CLOSED\n }\n\n /**\n * 是否已连接\n */\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN\n }\n\n /**\n * 获取 WebSocket 实例\n */\n getInstance(): WebSocket | null {\n return this.ws\n }\n\n /**\n * 设置事件处理器\n */\n on<K extends keyof WebSocketEventHandlers>(\n event: K,\n handler: WebSocketEventHandlers[K]\n ): void {\n this.handlers[event] = handler\n }\n\n /**\n * 移除事件处理器\n */\n off<K extends keyof WebSocketEventHandlers>(\n event: K,\n handler?: WebSocketEventHandlers[K]\n ): void {\n if (!handler || this.handlers[event] === handler) {\n delete this.handlers[event]\n }\n }\n\n /**\n * 重新连接\n */\n reconnect(): void {\n this.disconnect()\n this.reconnectCount = 0\n this.isManualDisconnect = false\n this.connect()\n }\n\n /**\n * 设置事件处理器\n */\n private setupEventHandlers(): void {\n if (!this.ws) return\n\n this.ws.onopen = (event) => {\n this.log('Connected')\n this.reconnectCount = 0\n\n // 发送队列中的消息\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift()\n if (message) {\n this.sendSync(message)\n }\n }\n\n // 启动心跳\n this.startHeartbeat()\n\n // 触发 onOpen 回调\n if (this.handlers.onOpen) {\n this.handlers.onOpen(event)\n }\n\n // 解析连接 Promise\n if (this.connectResolve) {\n this.connectResolve()\n this.connectResolve = null\n this.connectReject = null\n }\n }\n\n this.ws.onmessage = (event) => {\n this.log('Message received:', event.data)\n\n let data: WebSocketMessage = event.data\n\n // 尝试解析 JSON\n if (typeof event.data === 'string') {\n try {\n data = JSON.parse(event.data)\n } catch {\n // 不是 JSON 格式,保持原样\n }\n }\n\n // 触发 onMessage 回调\n if (this.handlers.onMessage) {\n this.handlers.onMessage(data, event)\n }\n }\n\n this.ws.onclose = (event) => {\n this.log('Connection closed:', event.code, event.reason)\n this.cleanup()\n\n // 触发 onClose 回调\n if (this.handlers.onClose) {\n this.handlers.onClose(event)\n }\n\n // 自动重连\n if (!this.isManualDisconnect && this.options.autoReconnect) {\n this.attemptReconnect()\n }\n }\n\n this.ws.onerror = (event) => {\n this.log('Error:', event)\n\n // 触发 onError 回调\n if (this.handlers.onError) {\n this.handlers.onError(event)\n }\n }\n }\n\n /**\n * 尝试重连\n */\n private attemptReconnect(): void {\n if (this.reconnectCount >= this.options.reconnectAttempts) {\n this.log('Reconnect failed, max attempts reached')\n this.cleanup()\n\n // 触发 onReconnectFailed 回调\n if (this.handlers.onReconnectFailed) {\n this.handlers.onReconnectFailed()\n }\n\n if (this.connectReject) {\n this.connectReject(new Error('Reconnect failed'))\n this.connectResolve = null\n this.connectReject = null\n }\n return\n }\n\n this.reconnectCount++\n this.log(`Reconnecting... Attempt ${this.reconnectCount}/${this.options.reconnectAttempts}`)\n\n // 触发 onReconnect 回调\n if (this.handlers.onReconnect) {\n this.handlers.onReconnect(this.reconnectCount)\n }\n\n this.reconnectTimer = setTimeout(() => {\n this.connect()\n }, this.options.reconnectInterval)\n }\n\n /**\n * 启动心跳\n */\n private startHeartbeat(): void {\n this.stopHeartbeat()\n\n this.heartbeatTimer = setInterval(() => {\n if (this.isConnected()) {\n const message = this.options.heartbeatMessage\n this.log('Sending heartbeat')\n\n // 触发 onHeartbeat 回调\n if (this.handlers.onHeartbeat) {\n this.handlers.onHeartbeat()\n }\n\n // 发送心跳消息\n this.sendSync(message)\n\n // 设置心跳超时检测\n this.heartbeatTimeoutTimer = setTimeout(() => {\n this.log('Heartbeat timeout')\n\n // 触发 onHeartbeatTimeout 回调\n if (this.handlers.onHeartbeatTimeout) {\n this.handlers.onHeartbeatTimeout()\n }\n\n // 关闭连接,触发重连\n if (this.ws) {\n this.ws.close()\n }\n }, this.options.heartbeatTimeout)\n }\n }, this.options.heartbeatInterval)\n }\n\n /**\n * 停止心跳\n */\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer)\n this.heartbeatTimer = null\n }\n if (this.heartbeatTimeoutTimer) {\n clearTimeout(this.heartbeatTimeoutTimer)\n this.heartbeatTimeoutTimer = null\n }\n }\n\n /**\n * 清理资源\n */\n private cleanup(): void {\n this.stopHeartbeat()\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n }\n\n /**\n * 处理错误\n */\n private handleError(error: Error): void {\n this.log('Error:', error.message)\n\n // 触发 onError 回调\n if (this.handlers.onError) {\n this.handlers.onError(new ErrorEvent('error', { error }))\n }\n }\n\n /**\n * 日志输出\n */\n private log(...args: unknown[]): void {\n if (this.options.debug) {\n console.log('[WebSocket]', ...args)\n }\n }\n}\n\n// ==================== 工厂函数 ====================\n\n/**\n * 创建 WebSocket 客户端\n * @param options - 配置选项\n * @returns WebSocket 客户端实例\n * @example\n * ```ts\n * const ws = createWebSocket({\n * url: 'echo.websocket.org',\n * autoReconnect: true,\n * onMessage: (data) => console.log('Received:', data)\n * })\n *\n * ws.send('Hello, WebSocket!')\n * ```\n */\nexport function createWebSocket(options: WebSocketOptions): IWebSocketClient {\n return new WebSocketClient(options)\n}\n\n/**\n * 快速连接 WebSocket\n * @param url - WebSocket 服务器地址\n * @param handlers - 事件处理器\n * @returns WebSocket 客户端实例\n * @example\n * ```ts\n * const ws = quickConnect('echo.websocket.org', {\n * onMessage: (data) => console.log('Received:', data)\n * })\n * ```\n */\nexport function quickConnect(\n url: string,\n handlers?: WebSocketEventHandlers\n): IWebSocketClient {\n const client = new WebSocketClient({ url, autoReconnect: true })\n\n if (handlers) {\n Object.entries(handlers).forEach(([event, handler]) => {\n client.on(event as keyof WebSocketEventHandlers, handler)\n })\n }\n\n return client\n}\n\n// ==================== 导出 ====================\n\nexport default {\n WebSocketClient,\n createWebSocket,\n quickConnect,\n WebSocketState,\n}\n"]}
@@ -0,0 +1 @@
1
+ export { I as IWebSocketClient, W as WebSocketClient, a as WebSocketEventHandlers, b as WebSocketMessage, c as WebSocketOptions, d as WebSocketState, e as createWebSocket, _ as default, q as quickConnect } from './index-Cq1GhjpY.cjs';
@@ -0,0 +1 @@
1
+ export { I as IWebSocketClient, W as WebSocketClient, a as WebSocketEventHandlers, b as WebSocketMessage, c as WebSocketOptions, d as WebSocketState, e as createWebSocket, _ as default, q as quickConnect } from './index-Cq1GhjpY.js';