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/common.d.ts +86 -0
- package/es/common.js +92 -0
- package/es/connection-manager.d.ts +83 -0
- package/es/connection-manager.js +434 -0
- package/es/error-handler.d.ts +45 -0
- package/es/error-handler.js +111 -0
- package/es/event-handler.d.ts +14 -0
- package/es/event-handler.js +215 -0
- package/es/heartbeat-manager.d.ts +37 -0
- package/es/heartbeat-manager.js +93 -0
- package/es/im.d.ts +162 -0
- package/es/im.interface.d.ts +234 -0
- package/es/im.interface.js +1 -0
- package/es/im.js +444 -0
- package/es/index.d.ts +7 -0
- package/es/index.js +8 -0
- package/es/logger.d.ts +98 -0
- package/es/logger.js +238 -0
- package/es/message-queue-manager.d.ts +45 -0
- package/es/message-queue-manager.js +128 -0
- package/es/message-sender.d.ts +26 -0
- package/es/message-sender.js +113 -0
- package/es/monitoring-manager.d.ts +48 -0
- package/es/monitoring-manager.js +161 -0
- package/es/reconnect.d.ts +19 -0
- package/es/reconnect.js +279 -0
- package/es/socket.d.ts +29 -0
- package/es/socket.js +163 -0
- package/es/types.d.ts +82 -0
- package/es/types.js +1 -0
- package/es/util.d.ts +11 -0
- package/es/util.js +44 -0
- package/package.json +1 -1
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
|
+
}
|