magic-chat-im 2.9.2 → 2.9.3

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/es/socket.js ADDED
@@ -0,0 +1,163 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
6
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
7
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
9
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
10
+ /**
11
+ * WebSocket
12
+ * https://html.spec.whatwg.org/multipage/web-sockets.html#network
13
+ */
14
+ import mitt from 'mitt';
15
+ import { IM_TYPE, WS_STATUS, WS_TYPE } from "./common";
16
+ import { logger } from "./logger";
17
+ import { errorHandler } from "./error-handler";
18
+ /**
19
+ * 旧参数,{token, serverDomain, userId, appId}
20
+ * const wsPath = `wss://${serverDomain}/gtsWebPush/ws`;
21
+ const wsQuery = `param=${appId},${userId},${token}`;
22
+ const wsUrl = `${wsPath}?${wsQuery}`;
23
+ * 新参数,{url,token, appKey}
24
+ * const url = `wss://${serverDomain}/gtsWebPush/ws`;
25
+ const appKey = `${appId},${userId}`;
26
+ const wsUrl = `${url}?param=${appKey},${token}`;
27
+ */
28
+ function getWsUrl(config) {
29
+ var url = config.url,
30
+ token = config.token,
31
+ appKey = config.appKey;
32
+ return "".concat(url, "?param=").concat(appKey, ",").concat(token);
33
+ }
34
+ var Socket = /*#__PURE__*/function () {
35
+ function Socket(config) {
36
+ _classCallCheck(this, Socket);
37
+ _defineProperty(this, "ws", void 0);
38
+ _defineProperty(this, "config", void 0);
39
+ _defineProperty(this, "emit", void 0);
40
+ _defineProperty(this, "on", void 0);
41
+ _defineProperty(this, "_eventHandlers", void 0);
42
+ var url = getWsUrl(config);
43
+ var ws = new WebSocket(url);
44
+ this._eventHandlers = {};
45
+ this._bindEvts(ws);
46
+ Object.assign(this, _objectSpread({
47
+ ws: ws,
48
+ config: config
49
+ }, mitt()));
50
+ }
51
+
52
+ /**
53
+ * 获取 WebSocket 的 readyState
54
+ */
55
+ _createClass(Socket, [{
56
+ key: "readyState",
57
+ get: function get() {
58
+ return this.ws.readyState;
59
+ }
60
+
61
+ /**
62
+ * 自动根据 WebSocket 的实际状态计算 status
63
+ * 使用 getter 避免状态不同步问题
64
+ */
65
+ }, {
66
+ key: "status",
67
+ get: function get() {
68
+ if (!this.ws) {
69
+ return WS_STATUS.OFFLINE;
70
+ }
71
+ switch (this.ws.readyState) {
72
+ case WebSocket.OPEN:
73
+ return WS_STATUS.ONLINE;
74
+ case WebSocket.CONNECTING:
75
+ case WebSocket.CLOSING:
76
+ case WebSocket.CLOSED:
77
+ default:
78
+ return WS_STATUS.OFFLINE;
79
+ }
80
+ }
81
+ }, {
82
+ key: "send",
83
+ value: function send(data) {
84
+ if (this.ws) this.ws.send(data);
85
+ }
86
+ }, {
87
+ key: "close",
88
+ value: function close() {
89
+ var _this$ws;
90
+ // 移除所有事件监听器
91
+ this._unbindEvts();
92
+ (_this$ws = this.ws) === null || _this$ws === void 0 || _this$ws.close();
93
+ }
94
+ }, {
95
+ key: "_bindEvts",
96
+ value: function _bindEvts(ws) {
97
+ var _this = this;
98
+ this._eventHandlers[WS_TYPE.OPEN] = function () {
99
+ // status 现在是 getter,会自动从 ws.readyState 计算,无需手动设置
100
+ _this.emit(IM_TYPE.OPEN);
101
+ logger.debug('[WebSocket] WebSocket open');
102
+ };
103
+ this._eventHandlers[WS_TYPE.MESSAGE] = function (ev) {
104
+ logger.debug("[WebSocket] WebSocket Message received", ev.data);
105
+ // status 会自动反映连接状态,无需手动设置
106
+ _this.emit(IM_TYPE.MESSAGE, {
107
+ type: IM_TYPE.MESSAGE,
108
+ data: ev.data
109
+ });
110
+ };
111
+ this._eventHandlers[WS_TYPE.ERROR] = function (err) {
112
+ var _this$config;
113
+ // 使用统一的错误处理中心记录详细的错误信息
114
+ errorHandler.reportError('[WebSocket] WebSocket error occurred', err, {
115
+ url: (_this$config = _this.config) === null || _this$config === void 0 ? void 0 : _this$config.url,
116
+ status: _this.status,
117
+ readyState: _this.readyState
118
+ });
119
+
120
+ // status 会自动反映连接状态,无需手动设置
121
+ _this.emit(IM_TYPE.ERROR, err);
122
+ };
123
+ this._eventHandlers[WS_TYPE.CLOSE] = function (err) {
124
+ // 记录连接关闭的详细信息,特别是code 1006的情况
125
+ if (err.code === 1006) {
126
+ errorHandler.reportError('[WebSocket] WebSocket closed abnormally with code 1006 (connection lost without proper close frame)', err, {
127
+ reason: err.reason,
128
+ wasClean: err.wasClean
129
+ });
130
+ } else {
131
+ logger.info('[WebSocket] WebSocket closed', {
132
+ code: err.code,
133
+ reason: err.reason,
134
+ wasClean: err.wasClean
135
+ });
136
+ }
137
+
138
+ // status 会自动反映连接状态,无需手动设置
139
+ _this.emit(IM_TYPE.CLOSE, err);
140
+ };
141
+
142
+ // 添加事件监听器
143
+ ws.addEventListener(WS_TYPE.OPEN, this._eventHandlers[WS_TYPE.OPEN]);
144
+ ws.addEventListener(WS_TYPE.MESSAGE, this._eventHandlers[WS_TYPE.MESSAGE]);
145
+ ws.addEventListener(WS_TYPE.ERROR, this._eventHandlers[WS_TYPE.ERROR]);
146
+ ws.addEventListener(WS_TYPE.CLOSE, this._eventHandlers[WS_TYPE.CLOSE]);
147
+ }
148
+ }, {
149
+ key: "_unbindEvts",
150
+ value: function _unbindEvts() {
151
+ var _this2 = this;
152
+ if (this.ws && this._eventHandlers) {
153
+ // 移除所有事件监听器
154
+ Object.keys(this._eventHandlers).forEach(function (eventType) {
155
+ _this2.ws.removeEventListener(eventType, _this2._eventHandlers[eventType]);
156
+ });
157
+ this._eventHandlers = {};
158
+ }
159
+ }
160
+ }]);
161
+ return Socket;
162
+ }();
163
+ export { Socket as default };
package/es/types.d.ts ADDED
@@ -0,0 +1,82 @@
1
+ /**
2
+ * IM SDK 类型定义
3
+ */
4
+ import { EXCEPTION_ERROR, RECEIVED_MSG_TYPE, RECONNECT_RESON, SEND_MSG_TYPE } from './common';
5
+ /**
6
+ * 消息数据结构
7
+ */
8
+ export interface MessageData {
9
+ name: string;
10
+ args?: any[];
11
+ messageKey: string;
12
+ msgType: RECEIVED_MSG_TYPE | SEND_MSG_TYPE;
13
+ msgBody: MessageBody;
14
+ appId?: string;
15
+ userId?: string;
16
+ }
17
+ /**
18
+ * 消息体结构
19
+ */
20
+ export interface MessageBody {
21
+ version?: string;
22
+ msgType?: string;
23
+ msgDetail?: any;
24
+ [key: string]: any;
25
+ }
26
+ /**
27
+ * 重连事件数据
28
+ */
29
+ export interface ReconnectEventData {
30
+ code: RECONNECT_RESON;
31
+ err?: any;
32
+ attempt?: number;
33
+ maxRetries?: number;
34
+ nextRetryDelay?: number;
35
+ isReconnecting?: boolean;
36
+ }
37
+ /**
38
+ * 错误事件数据
39
+ */
40
+ export interface ErrorEventData {
41
+ code: EXCEPTION_ERROR;
42
+ err?: any;
43
+ msg?: string;
44
+ reason?: string;
45
+ maxRetry?: number;
46
+ [key: string]: any;
47
+ }
48
+ /**
49
+ * 关闭事件数据
50
+ */
51
+ export interface CloseEventData {
52
+ code: EXCEPTION_ERROR;
53
+ err?: any;
54
+ reason?: string;
55
+ [key: string]: any;
56
+ }
57
+ /**
58
+ * WebSocket 消息
59
+ */
60
+ export interface WS_Message {
61
+ type: string;
62
+ data: string;
63
+ }
64
+ /**
65
+ * ACK 消息
66
+ */
67
+ export interface AckMessage {
68
+ messageKey: string;
69
+ appId?: string;
70
+ userId?: string;
71
+ msgType: SEND_MSG_TYPE;
72
+ }
73
+ /**
74
+ * 发送消息格式
75
+ */
76
+ export interface SendMessageData {
77
+ appId?: string;
78
+ userId?: string;
79
+ messageKey: string;
80
+ msgType: SEND_MSG_TYPE;
81
+ msgBody: MessageBody;
82
+ }
package/es/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/es/util.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export declare function getMsgBody(msg: string): any | null;
2
+ export declare function makeMsgBody(msg: Record<string, any>): string;
3
+ /**
4
+ * https://stackoverflow.com/questions/44815172/log-shows-error-object-istrustedtrue-instead-of-actual-error-data
5
+ */
6
+ export declare function getError(err: any): string;
7
+ /**
8
+ * 检测是否为移动端设备
9
+ * @returns {boolean} 是否为移动端
10
+ */
11
+ export declare function isMobile(): boolean;
package/es/util.js ADDED
@@ -0,0 +1,44 @@
1
+ import { logger } from "./logger";
2
+ export function getMsgBody(msg) {
3
+ if (!msg) {
4
+ logger.warn('[utils] getMsgBody: Empty message received');
5
+ return null;
6
+ }
7
+ try {
8
+ return JSON.parse(msg);
9
+ } catch (e) {
10
+ logger.error('[utils] getMsgBody: Failed to parse message', {
11
+ error: e,
12
+ message: msg.substring(0, 100) // 只记录前 100 字符
13
+ });
14
+
15
+ // 可以上报到监控系统
16
+ // reportError('MESSAGE_PARSE_ERROR', e);
17
+
18
+ return null; // 返回 null 而不是原始字符串
19
+ }
20
+ }
21
+ export function makeMsgBody(msg) {
22
+ return "".concat(JSON.stringify(msg));
23
+ }
24
+
25
+ /**
26
+ * https://stackoverflow.com/questions/44815172/log-shows-error-object-istrustedtrue-instead-of-actual-error-data
27
+ */
28
+ export function getError(err) {
29
+ var res = err;
30
+ try {
31
+ res = JSON.stringify(err, ['message', 'arguments', 'type', 'name', 'code', 'reason']);
32
+ } catch (e) {
33
+ logger.error('[utils] getError: Failed to stringify error', e);
34
+ }
35
+ return res;
36
+ }
37
+
38
+ /**
39
+ * 检测是否为移动端设备
40
+ * @returns {boolean} 是否为移动端
41
+ */
42
+ export function isMobile() {
43
+ return /Android|iPhone|iPad|iPod|Windows Phone/i.test(navigator.userAgent);
44
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magic-chat-im",
3
- "version": "2.9.2",
3
+ "version": "2.9.3",
4
4
  "license": "ISC",
5
5
  "sideEffects": [
6
6
  "**/*.scss",