@das-fed/upf-utils 6.4.0-dev.291 → 6.4.0-dev.292

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 (47) hide show
  1. package/api-services/modules/app-manage/es5.js +1110 -1120
  2. package/api-services/modules/app-manage/index.js +918 -932
  3. package/api-services/modules/app-manage/index.js.gz +0 -0
  4. package/api-services/modules/authentication/es5.js +857 -860
  5. package/api-services/modules/authentication/index.js +670 -674
  6. package/api-services/modules/authentication/index.js.gz +0 -0
  7. package/api-services/modules/bems/es5.js +856 -854
  8. package/api-services/modules/bems/index.js +674 -670
  9. package/api-services/modules/bems/index.js.gz +0 -0
  10. package/api-services/modules/es5.js +1355 -1367
  11. package/api-services/modules/file/es5.js +1224 -1221
  12. package/api-services/modules/file/index.js +997 -993
  13. package/api-services/modules/file/index.js.gz +0 -0
  14. package/api-services/modules/index.js +1068 -1086
  15. package/api-services/modules/index.js.gz +0 -0
  16. package/api-services/modules/link/es5.js +1124 -1133
  17. package/api-services/modules/link/index.js +933 -947
  18. package/api-services/modules/link/index.js.gz +0 -0
  19. package/api-services/modules/permission/es5.js +1134 -1122
  20. package/api-services/modules/permission/index.js +948 -930
  21. package/api-services/modules/permission/index.js.gz +0 -0
  22. package/api-services/modules/super-admin/es5.js +864 -861
  23. package/api-services/modules/super-admin/index.js +676 -672
  24. package/api-services/modules/super-admin/index.js.gz +0 -0
  25. package/api-services/modules/tool/es5.js +1122 -1134
  26. package/api-services/modules/tool/index.js +930 -948
  27. package/api-services/modules/tool/index.js.gz +0 -0
  28. package/api-services/src/create-service/es5.js +1120 -1132
  29. package/api-services/src/create-service/index.js +929 -947
  30. package/api-services/src/create-service/index.js.gz +0 -0
  31. package/browser-importmap.json +22 -0
  32. package/browser.d.ts +11 -0
  33. package/browser.js +198 -51
  34. package/browser.js.gz +0 -0
  35. package/common-info/getPermissionMethod/es5.js +1388 -1376
  36. package/common-info/getPermissionMethod/index.js +1155 -1137
  37. package/common-info/getPermissionMethod/index.js.gz +0 -0
  38. package/create-api-service/es5.js +1121 -1131
  39. package/create-api-service/index.js +930 -944
  40. package/create-api-service/index.js.gz +0 -0
  41. package/package.json +7 -7
  42. package/realtime-connection/es5.d.ts +12 -1
  43. package/realtime-connection/es5.js +205 -129
  44. package/realtime-connection/index.d.ts +12 -1
  45. package/realtime-connection/index.js +139 -91
  46. package/realtime-connection/index.js.gz +0 -0
  47. package/release-meta.json +4 -4
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@das-fed/upf-utils",
3
- "version": "6.4.0-dev.291",
3
+ "version": "6.4.0-dev.292",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -22,8 +22,8 @@
22
22
  },
23
23
  "devDependencies": {
24
24
  "@babel/preset-env": "7.26.0",
25
- "@das-fed/upf-cli": "6.4.0-dev.291",
26
- "@das-fed/upf-web": "6.4.0-dev.291",
25
+ "@das-fed/upf-cli": "6.4.0-dev.292",
26
+ "@das-fed/upf-web": "6.4.0-dev.292",
27
27
  "@rollup/plugin-babel": "6.0.4",
28
28
  "@types/js-cookie": "^3.0.6",
29
29
  "@types/lodash-es": "^4.17.12",
@@ -51,13 +51,13 @@
51
51
  },
52
52
  "upfReleaseMeta": {
53
53
  "packageName": "@das-fed/upf-utils",
54
- "releaseVersion": "6.4.0-dev.291",
54
+ "releaseVersion": "6.4.0-dev.292",
55
55
  "distTag": "dev",
56
56
  "releaseType": "publish",
57
- "publishedAt": "2026-07-13T02:00:37.590Z",
57
+ "publishedAt": "2026-07-14T06:46:37.761Z",
58
58
  "sourceBranch": "dev",
59
- "sourceCommit": "14810ecd88ae0e6ec2d3e6eb686b3fddde26e908",
60
- "gitTag": "upf-release/v6.4.0-dev.291",
59
+ "sourceCommit": "9766fa3af4bca90be90632cab0c7653f16f56bfe",
60
+ "gitTag": "upf-release/v6.4.0-dev.292",
61
61
  "gitRemote": "origin",
62
62
  "gitRemoteUrl": "http://gitlab.dasiot.cn/foundation/frontend/framework.git",
63
63
  "releaseStatus": "success"
@@ -1,8 +1,11 @@
1
1
  export type RealtimeSocketState = 'idle' | 'waiting-token' | 'connecting' | 'open' | 'reconnecting' | 'closed' | 'unsupported';
2
2
  export type RealtimeSocketHeartbeatOptions = {
3
3
  message: string | (() => string);
4
+ /** 心跳间隔(毫秒),仅接受浏览器定时器支持范围内的正数。 */
4
5
  interval: number;
6
+ /** 等待 response 的超时时间(毫秒);未配置 response 时不启用应答超时。 */
5
7
  timeout?: number;
8
+ /** 服务端心跳响应内容,可配置一个或多个精确匹配值。 */
6
9
  response?: string | string[];
7
10
  };
8
11
  export type RealtimeSocketReconnectOptions = {
@@ -37,7 +40,9 @@ export declare class RealtimeSocketClient<T = unknown> {
37
40
  private reconnectAttempts;
38
41
  private manualClosed;
39
42
  private started;
40
- private lastHeartbeatAck;
43
+ private opening;
44
+ private openVersion;
45
+ private heartbeatSequence;
41
46
  constructor(options: RealtimeSocketClientOptions<T>);
42
47
  /** 获取当前连接状态,供业务显示或调试兜底使用。 */
43
48
  getState(): RealtimeSocketState;
@@ -53,13 +58,19 @@ export declare class RealtimeSocketClient<T = unknown> {
53
58
  private handleMessage;
54
59
  private handleClose;
55
60
  private handleError;
61
+ /** 启动单实例心跳;等待应答期间不重复发送,避免 interval 与 timeout 竞争。 */
56
62
  private startHeartbeat;
63
+ /** 心跳发送或应答超时后,仅关闭当前连接并进入既有重连流程。 */
64
+ private handleHeartbeatFailure;
57
65
  private scheduleReconnect;
58
66
  private getReconnectDelay;
59
67
  private handleOnline;
60
68
  private handleOffline;
61
69
  private setState;
62
70
  private closeSocket;
71
+ private cancelPendingOpen;
72
+ private isCurrentOpen;
73
+ private isCurrentSocket;
63
74
  private clearTimers;
64
75
  private clearHeartbeatTimers;
65
76
  private clearHeartbeatTimeoutTimer;
@@ -15,38 +15,45 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
15
15
  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); }
16
16
  var config = require('@das-fed/upf-utils/config/es5');
17
17
  var commonTools = require('@das-fed/upf-utils/common-tools/es5');
18
- var l = 3e3,
19
- u = 3e4,
20
- m = function m() {
21
- var i = config.getConfig(),
22
- t = i.wsBaseURL || i.baseURL || location.origin;
23
- return String(t || "").replace(/^https:/i, "wss:").replace(/^http:/i, "ws:").replace(/\/+$/, "");
18
+ var m = 3e3,
19
+ d = 3e4,
20
+ f = 2147483647,
21
+ p = function p() {
22
+ var n = config.getConfig(),
23
+ e = n.wsBaseURL || n.baseURL || location.origin;
24
+ return String(e || "").replace(/^https:/i, "wss:").replace(/^http:/i, "ws:").replace(/\/+$/, "");
24
25
  },
25
- d = function d(i) {
26
- return /^wss?:\/\//i.test(i);
26
+ T = function T(n) {
27
+ return /^wss?:\/\//i.test(n);
27
28
  },
28
- f = function f(i) {
29
- return /^https?:\/\//i.test(i);
29
+ S = function S(n) {
30
+ return /^https?:\/\//i.test(n);
30
31
  },
31
- p = function p(i, t) {
32
- var e = String(i || "").trim(),
33
- s = d(e) ? e : f(e) ? e.replace(/^https:/i, "wss:").replace(/^http:/i, "ws:") : "".concat(m()).concat(e.startsWith("/") ? e : "/".concat(e)),
34
- r = commonTools.objectToUrlparams(t);
35
- return r ? "".concat(s).concat(s.includes("?") ? "&" : "?").concat(r) : s;
32
+ g = function g(n, e) {
33
+ var t = String(n || "").trim(),
34
+ s = T(t) ? t : S(t) ? t.replace(/^https:/i, "wss:").replace(/^http:/i, "ws:") : "".concat(p()).concat(t.startsWith("/") ? t : "/".concat(t)),
35
+ i = commonTools.objectToUrlparams(e);
36
+ return i ? "".concat(s).concat(s.includes("?") ? "&" : "?").concat(i) : s;
36
37
  },
37
- T = function T(i, t) {
38
- return t ? (Array.isArray(t) ? t : [t]).includes(String(i !== null && i !== void 0 ? i : "")) : false;
38
+ b = function b(n, e) {
39
+ return e ? (Array.isArray(e) ? e : [e]).includes(String(n !== null && n !== void 0 ? n : "")) : false;
39
40
  },
40
- b = function b(i) {
41
- return typeof i.data == "string" ? JSON.parse(i.data) : i.data;
41
+ w = function w(n) {
42
+ return (Array.isArray(n) || typeof n == "string") && n.length > 0;
43
+ },
44
+ c = function c(n) {
45
+ return Number.isFinite(n) && n >= 1 && n <= f;
46
+ },
47
+ k = function k(n) {
48
+ return typeof n.data == "string" ? JSON.parse(n.data) : n.data;
42
49
  };
43
- var S = /*#__PURE__*/function () {
44
- function S(t) {
45
- _classCallCheck(this, S);
46
- this.ws = null, this.state = "idle", this.heartbeatTimer = null, this.heartbeatTimeoutTimer = null, this.reconnectTimer = null, this.reconnectAttempts = 0, this.manualClosed = false, this.started = false, this.lastHeartbeatAck = true, this.options = t, this.handleOnline = this.handleOnline.bind(this), this.handleOffline = this.handleOffline.bind(this);
50
+ var y = /*#__PURE__*/function () {
51
+ function y(e) {
52
+ _classCallCheck(this, y);
53
+ this.ws = null, this.state = "idle", this.heartbeatTimer = null, this.heartbeatTimeoutTimer = null, this.reconnectTimer = null, this.reconnectAttempts = 0, this.manualClosed = false, this.started = false, this.opening = false, this.openVersion = 0, this.heartbeatSequence = 0, this.options = e, this.handleOnline = this.handleOnline.bind(this), this.handleOffline = this.handleOffline.bind(this);
47
54
  }
48
55
  /** 获取当前连接状态,供业务显示或调试兜底使用。 */
49
- return _createClass(S, [{
56
+ return _createClass(y, [{
50
57
  key: "getState",
51
58
  value: function getState() {
52
59
  return this.state;
@@ -59,7 +66,7 @@ var S = /*#__PURE__*/function () {
59
66
  return _regenerator().w(function (_context) {
60
67
  while (1) switch (_context.n) {
61
68
  case 0:
62
- if (this.started && (this.state === "connecting" || this.state === "open" || this.state === "reconnecting")) {
69
+ if (this.started && (this.state === "waiting-token" || this.state === "connecting" || this.state === "open" || this.state === "reconnecting")) {
63
70
  _context.n = 2;
64
71
  break;
65
72
  }
@@ -85,63 +92,94 @@ var S = /*#__PURE__*/function () {
85
92
  }() /** 仅在连接已打开时发送消息,失败时返回 false。 */)
86
93
  }, {
87
94
  key: "send",
88
- value: function send(t) {
89
- var e;
90
- return ((e = this.ws) == null ? undefined : e.readyState) !== WebSocket.OPEN ? false : (this.ws.send(t), true);
95
+ value: function send(e) {
96
+ var t = this.ws;
97
+ if (!t || t.readyState !== WebSocket.OPEN) return false;
98
+ try {
99
+ return t.send(e), !0;
100
+ } catch (_unused) {
101
+ return false;
102
+ }
91
103
  }
92
104
  /** 主动关闭连接,并清理心跳、重连和网络监听。 */
93
105
  }, {
94
106
  key: "close",
95
107
  value: function close() {
96
- this.manualClosed = true, this.started = false, this.clearTimers(), this.removeNetworkListeners(), this.closeSocket(), this.setState("closed");
108
+ this.manualClosed = true, this.started = false, this.cancelPendingOpen(), this.clearTimers(), this.removeNetworkListeners(), this.closeSocket(), this.setState("closed");
97
109
  }
98
110
  }, {
99
111
  key: "openSocket",
100
112
  value: function () {
101
113
  var _openSocket = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
102
114
  var _this = this;
103
- var s, r, t, e, n;
115
+ var i, o, e, t, s, r, _t;
104
116
  return _regenerator().w(function (_context2) {
105
- while (1) switch (_context2.n) {
117
+ while (1) switch (_context2.p = _context2.n) {
106
118
  case 0:
107
- if (!this.manualClosed) {
119
+ if (!(!this.started || this.manualClosed || this.opening)) {
108
120
  _context2.n = 1;
109
121
  break;
110
122
  }
111
123
  return _context2.a(2);
112
124
  case 1:
113
- this.clearReconnectTimer(), this.closeSocket(), this.setState(this.reconnectAttempts > 0 ? "reconnecting" : "connecting");
114
- t = _objectSpread({}, this.options.params || {});
115
- _context2.n = 2;
116
- return this.resolveToken();
117
- case 2:
118
- e = _context2.v;
119
- if (!(this.options.tokenProvider && !e)) {
120
- _context2.n = 3;
125
+ if (!((typeof navigator === "undefined" ? "undefined" : _typeof(navigator)) < "u" && navigator.onLine === false)) {
126
+ _context2.n = 2;
121
127
  break;
122
128
  }
123
- this.scheduleReconnect("waiting-token");
129
+ this.setState(this.reconnectAttempts > 0 ? "reconnecting" : "waiting-token");
124
130
  return _context2.a(2);
131
+ case 2:
132
+ e = ++this.openVersion;
133
+ this.opening = true, this.clearReconnectTimer(), this.clearHeartbeatTimers(), this.closeSocket(), this.setState(this.reconnectAttempts > 0 ? "reconnecting" : "connecting");
134
+ t = _objectSpread({}, this.options.params || {});
135
+ _context2.n = 3;
136
+ return this.resolveToken();
125
137
  case 3:
126
- e && (t[this.options.tokenParamName || "access_token"] = e);
127
- try {
128
- n = new WebSocket(p(this.options.url, t));
129
- this.ws = n, n.onopen = function (o) {
130
- return _this.handleOpen(o);
131
- }, n.onmessage = function (o) {
132
- return _this.handleMessage(o);
133
- }, n.onclose = function (o) {
134
- return _this.handleClose(o);
135
- }, n.onerror = function (o) {
136
- return _this.handleError(o);
137
- };
138
- } catch (n) {
139
- (r = (s = this.options).onInvalidMessage) == null || r.call(s, n, {}), this.scheduleReconnect();
138
+ s = _context2.v;
139
+ if (!this.isCurrentOpen(e)) {
140
+ _context2.n = 9;
141
+ break;
140
142
  }
143
+ if (!(this.options.tokenProvider && !s)) {
144
+ _context2.n = 4;
145
+ break;
146
+ }
147
+ this.opening = false, this.scheduleReconnect("waiting-token");
148
+ return _context2.a(2);
141
149
  case 4:
150
+ s && (t[this.options.tokenParamName || "access_token"] = s);
151
+ _context2.p = 5;
152
+ r = new WebSocket(g(this.options.url, t));
153
+ if (this.isCurrentOpen(e)) {
154
+ _context2.n = 6;
155
+ break;
156
+ }
157
+ r.close();
158
+ return _context2.a(2);
159
+ case 6:
160
+ this.ws = r, r.onopen = function (a) {
161
+ return _this.handleOpen(r, a);
162
+ }, r.onmessage = function (a) {
163
+ return _this.handleMessage(r, a);
164
+ }, r.onclose = function (a) {
165
+ return _this.handleClose(r, a);
166
+ }, r.onerror = function (a) {
167
+ return _this.handleError(r, a);
168
+ };
169
+ _context2.n = 8;
170
+ break;
171
+ case 7:
172
+ _context2.p = 7;
173
+ _t = _context2.v;
174
+ this.isCurrentOpen(e) && ((o = (i = this.options).onInvalidMessage) == null || o.call(i, _t, {}), this.scheduleReconnect());
175
+ case 8:
176
+ _context2.p = 8;
177
+ this.openVersion === e && (this.opening = false);
178
+ return _context2.f(8);
179
+ case 9:
142
180
  return _context2.a(2);
143
181
  }
144
- }, _callee2, this);
182
+ }, _callee2, this, [[5, 7, 8, 9]]);
145
183
  }));
146
184
  function openSocket() {
147
185
  return _openSocket.apply(this, arguments);
@@ -152,7 +190,7 @@ var S = /*#__PURE__*/function () {
152
190
  key: "resolveToken",
153
191
  value: function () {
154
192
  var _resolveToken = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
155
- var _t, _t2, _t3;
193
+ var _t2, _t3, _t4;
156
194
  return _regenerator().w(function (_context3) {
157
195
  while (1) switch (_context3.p = _context3.n) {
158
196
  case 0:
@@ -163,21 +201,21 @@ var S = /*#__PURE__*/function () {
163
201
  return _context3.a(2, "");
164
202
  case 1:
165
203
  _context3.p = 1;
166
- _t = String;
204
+ _t2 = String;
167
205
  _context3.n = 2;
168
206
  return this.options.tokenProvider();
169
207
  case 2:
170
- _t2 = _context3.v;
171
- if (_t2) {
208
+ _t3 = _context3.v;
209
+ if (_t3) {
172
210
  _context3.n = 3;
173
211
  break;
174
212
  }
175
- _t2 = "";
213
+ _t3 = "";
176
214
  case 3:
177
- return _context3.a(2, _t(_t2).trim());
215
+ return _context3.a(2, _t2(_t3).trim());
178
216
  case 4:
179
217
  _context3.p = 4;
180
- _t3 = _context3.v;
218
+ _t4 = _context3.v;
181
219
  return _context3.a(2, "");
182
220
  }
183
221
  }, _callee3, this, [[1, 4]]);
@@ -189,122 +227,160 @@ var S = /*#__PURE__*/function () {
189
227
  }()
190
228
  }, {
191
229
  key: "handleOpen",
192
- value: function handleOpen(t) {
193
- var e, s;
194
- this.reconnectAttempts = 0, this.lastHeartbeatAck = true, this.setState("open"), (s = (e = this.options).onOpen) == null || s.call(e, t), this.startHeartbeat();
230
+ value: function handleOpen(e, t) {
231
+ var s, i;
232
+ this.isCurrentSocket(e) && (this.reconnectAttempts = 0, this.setState("open"), (i = (s = this.options).onOpen) == null || i.call(s, t), this.startHeartbeat());
195
233
  }
196
234
  }, {
197
235
  key: "handleMessage",
198
- value: function handleMessage(t) {
199
- var e, s, r, n, o;
200
- if (T(t.data, (e = this.options.heartbeat) == null ? undefined : e.response)) {
201
- this.lastHeartbeatAck = true, this.clearHeartbeatTimeoutTimer();
202
- return;
203
- }
204
- try {
205
- var a = this.options.parser || b;
206
- (r = (s = this.options).onMessage) == null || r.call(s, a(t), t);
207
- } catch (a) {
208
- (o = (n = this.options).onInvalidMessage) == null || o.call(n, a, t);
236
+ value: function handleMessage(e, t) {
237
+ var s, i, o, r, a;
238
+ if (this.isCurrentSocket(e)) {
239
+ if (b(t.data, (s = this.options.heartbeat) == null ? undefined : s.response)) {
240
+ this.clearHeartbeatTimeoutTimer();
241
+ return;
242
+ }
243
+ try {
244
+ var h = this.options.parser || k;
245
+ (o = (i = this.options).onMessage) == null || o.call(i, h(t), t);
246
+ } catch (h) {
247
+ (a = (r = this.options).onInvalidMessage) == null || a.call(r, h, t);
248
+ }
209
249
  }
210
250
  }
211
251
  }, {
212
252
  key: "handleClose",
213
- value: function handleClose(t) {
214
- var e, s;
215
- if (this.clearHeartbeatTimers(), (s = (e = this.options).onClose) == null || s.call(e, t), this.manualClosed) {
216
- this.setState("closed");
217
- return;
253
+ value: function handleClose(e, t) {
254
+ var s, i;
255
+ if (this.isCurrentSocket(e)) {
256
+ if (this.clearHeartbeatTimers(), this.ws = null, (i = (s = this.options).onClose) == null || i.call(s, t), this.manualClosed) {
257
+ this.setState("closed");
258
+ return;
259
+ }
260
+ this.scheduleReconnect();
218
261
  }
219
- this.scheduleReconnect();
220
262
  }
221
263
  }, {
222
264
  key: "handleError",
223
- value: function handleError(t) {
224
- var e, s;
225
- (s = (e = this.options).onError) == null || s.call(e, t);
265
+ value: function handleError(e, t) {
266
+ var s, i;
267
+ this.isCurrentSocket(e) && ((i = (s = this.options).onError) == null || i.call(s, t));
226
268
  }
269
+ /** 启动单实例心跳;等待应答期间不重复发送,避免 interval 与 timeout 竞争。 */
227
270
  }, {
228
271
  key: "startHeartbeat",
229
272
  value: function startHeartbeat() {
230
273
  var _this2 = this;
231
- var t = this.options.heartbeat;
232
- !(t != null && t.message) || !t.interval || (this.clearHeartbeatTimers(), this.heartbeatTimer = setInterval(function () {
233
- if (!_this2.ws || _this2.ws.readyState !== WebSocket.OPEN) return;
234
- if (t.timeout && !_this2.lastHeartbeatAck) {
235
- _this2.closeSocket(), _this2.scheduleReconnect();
274
+ var e = this.options.heartbeat,
275
+ t = Number(e == null ? undefined : e.interval);
276
+ if (!(e != null && e.message) || !c(t)) return;
277
+ var s = Number(e.timeout),
278
+ i = w(e.response) && c(s);
279
+ this.clearHeartbeatTimers(), this.heartbeatTimer = setInterval(function () {
280
+ var o = _this2.ws;
281
+ if (!o || o.readyState !== WebSocket.OPEN || i && _this2.heartbeatTimeoutTimer !== null) return;
282
+ var r;
283
+ try {
284
+ r = typeof e.message == "function" ? e.message() : e.message;
285
+ } catch (_unused3) {
286
+ _this2.handleHeartbeatFailure(o);
287
+ return;
288
+ }
289
+ if (!_this2.send(r)) {
290
+ _this2.handleHeartbeatFailure(o);
236
291
  return;
237
292
  }
238
- var e = typeof t.message == "function" ? t.message() : t.message;
239
- _this2.lastHeartbeatAck = false, _this2.send(e), t.timeout && (_this2.clearHeartbeatTimeoutTimer(), _this2.heartbeatTimeoutTimer = setTimeout(function () {
240
- _this2.lastHeartbeatAck || _this2.manualClosed || (_this2.closeSocket(), _this2.scheduleReconnect());
241
- }, t.timeout));
242
- }, t.interval));
293
+ if (!i) return;
294
+ _this2.clearHeartbeatTimeoutTimer();
295
+ var a = _this2.heartbeatSequence;
296
+ _this2.heartbeatTimeoutTimer = setTimeout(function () {
297
+ _this2.heartbeatSequence !== a || _this2.manualClosed || !_this2.isCurrentSocket(o) || _this2.handleHeartbeatFailure(o);
298
+ }, s);
299
+ }, t);
300
+ }
301
+ /** 心跳发送或应答超时后,仅关闭当前连接并进入既有重连流程。 */
302
+ }, {
303
+ key: "handleHeartbeatFailure",
304
+ value: function handleHeartbeatFailure(e) {
305
+ this.manualClosed || !this.isCurrentSocket(e) || (this.clearHeartbeatTimers(), this.closeSocket(), this.scheduleReconnect());
243
306
  }
244
307
  }, {
245
308
  key: "scheduleReconnect",
246
309
  value: function scheduleReconnect() {
247
310
  var _this3 = this;
248
- var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "reconnecting";
249
- var n;
250
- if (this.manualClosed || !((n = this.options.reconnect) != null && n.enabled)) {
311
+ var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "reconnecting";
312
+ var o;
313
+ if (this.manualClosed || !((o = this.options.reconnect) != null && o.enabled)) {
251
314
  this.setState("closed");
252
315
  return;
253
316
  }
254
317
  if ((typeof navigator === "undefined" ? "undefined" : _typeof(navigator)) < "u" && navigator.onLine === false) {
255
- this.setState(t);
318
+ this.setState(e);
319
+ return;
320
+ }
321
+ if (this.reconnectTimer) {
322
+ this.setState(e);
256
323
  return;
257
324
  }
258
325
  var _this$options$reconne = this.options.reconnect,
259
- e = _this$options$reconne.maxAttempts,
326
+ t = _this$options$reconne.maxAttempts,
260
327
  s = _this$options$reconne.jitter;
261
- if (typeof e == "number" && e >= 0 && this.reconnectAttempts >= e) {
328
+ if (typeof t == "number" && t >= 0 && this.reconnectAttempts >= t) {
262
329
  this.setState("closed");
263
330
  return;
264
331
  }
265
332
  this.reconnectAttempts += 1;
266
- var r = this.getReconnectDelay();
267
- this.setState(t), this.clearReconnectTimer(), this.reconnectTimer = setTimeout(function () {
268
- if (s) {
269
- setTimeout(function () {
270
- return _this3.openSocket();
271
- }, Math.floor(Math.random() * 300));
272
- return;
273
- }
274
- _this3.openSocket();
275
- }, r);
333
+ var i = this.getReconnectDelay();
334
+ this.setState(e), this.clearReconnectTimer(), this.reconnectTimer = setTimeout(function () {
335
+ _this3.reconnectTimer = null, _this3.openSocket();
336
+ }, i + (s ? Math.floor(Math.random() * 300) : 0));
276
337
  }
277
338
  }, {
278
339
  key: "getReconnectDelay",
279
340
  value: function getReconnectDelay() {
280
- var t = this.options.reconnect || {
341
+ var e = this.options.reconnect || {
281
342
  enabled: false
282
343
  },
283
- e = t.delay || l,
284
- s = t.maxDelay || u;
285
- return Math.min(e * Math.pow(2, Math.max(0, this.reconnectAttempts - 1)), s);
344
+ t = e.delay || m,
345
+ s = e.maxDelay || d;
346
+ return Math.min(t * Math.pow(2, Math.max(0, this.reconnectAttempts - 1)), s);
286
347
  }
287
348
  }, {
288
349
  key: "handleOnline",
289
350
  value: function handleOnline() {
290
- !this.started || this.manualClosed || this.state === "open" || this.state === "connecting" || this.openSocket();
351
+ !this.started || this.manualClosed || this.opening || this.state === "open" || this.state === "connecting" || this.openSocket();
291
352
  }
292
353
  }, {
293
354
  key: "handleOffline",
294
355
  value: function handleOffline() {
295
- this.manualClosed || (this.clearReconnectTimer(), this.closeSocket(), this.setState("reconnecting"));
356
+ this.manualClosed || (this.cancelPendingOpen(), this.clearTimers(), this.closeSocket(), this.setState("reconnecting"));
296
357
  }
297
358
  }, {
298
359
  key: "setState",
299
- value: function setState(t) {
300
- var e, s;
301
- this.state !== t && (this.state = t, (s = (e = this.options).onStateChange) == null || s.call(e, t));
360
+ value: function setState(e) {
361
+ var t, s;
362
+ this.state !== e && (this.state = e, (s = (t = this.options).onStateChange) == null || s.call(t, e));
302
363
  }
303
364
  }, {
304
365
  key: "closeSocket",
305
366
  value: function closeSocket() {
306
- var t = this.ws;
307
- t && (t.onopen = null, t.onmessage = null, t.onclose = null, t.onerror = null, (t.readyState === WebSocket.OPEN || t.readyState === WebSocket.CONNECTING) && t.close(), this.ws = null);
367
+ var e = this.ws;
368
+ e && (e.onopen = null, e.onmessage = null, e.onclose = null, e.onerror = null, (e.readyState === WebSocket.OPEN || e.readyState === WebSocket.CONNECTING) && e.close(), this.ws = null);
369
+ }
370
+ }, {
371
+ key: "cancelPendingOpen",
372
+ value: function cancelPendingOpen() {
373
+ this.openVersion += 1, this.opening = false;
374
+ }
375
+ }, {
376
+ key: "isCurrentOpen",
377
+ value: function isCurrentOpen(e) {
378
+ return this.started && !this.manualClosed && this.openVersion === e;
379
+ }
380
+ }, {
381
+ key: "isCurrentSocket",
382
+ value: function isCurrentSocket(e) {
383
+ return this.ws === e;
308
384
  }
309
385
  }, {
310
386
  key: "clearTimers",
@@ -314,12 +390,12 @@ var S = /*#__PURE__*/function () {
314
390
  }, {
315
391
  key: "clearHeartbeatTimers",
316
392
  value: function clearHeartbeatTimers() {
317
- this.heartbeatTimer && clearInterval(this.heartbeatTimer), this.heartbeatTimer = null, this.clearHeartbeatTimeoutTimer();
393
+ this.heartbeatTimer !== null && clearInterval(this.heartbeatTimer), this.heartbeatTimer = null, this.clearHeartbeatTimeoutTimer();
318
394
  }
319
395
  }, {
320
396
  key: "clearHeartbeatTimeoutTimer",
321
397
  value: function clearHeartbeatTimeoutTimer() {
322
- this.heartbeatTimeoutTimer && clearTimeout(this.heartbeatTimeoutTimer), this.heartbeatTimeoutTimer = null;
398
+ this.heartbeatSequence += 1, this.heartbeatTimeoutTimer !== null && clearTimeout(this.heartbeatTimeoutTimer), this.heartbeatTimeoutTimer = null;
323
399
  }
324
400
  }, {
325
401
  key: "clearReconnectTimer",
@@ -333,8 +409,8 @@ var S = /*#__PURE__*/function () {
333
409
  }
334
410
  }]);
335
411
  }();
336
- var g = function g(i) {
337
- return new S(i);
412
+ var A = function A(n) {
413
+ return new y(n);
338
414
  };
339
- exports.RealtimeSocketClient = S;
340
- exports.createRealtimeSocketClient = g;
415
+ exports.RealtimeSocketClient = y;
416
+ exports.createRealtimeSocketClient = A;
@@ -1,8 +1,11 @@
1
1
  export type RealtimeSocketState = 'idle' | 'waiting-token' | 'connecting' | 'open' | 'reconnecting' | 'closed' | 'unsupported';
2
2
  export type RealtimeSocketHeartbeatOptions = {
3
3
  message: string | (() => string);
4
+ /** 心跳间隔(毫秒),仅接受浏览器定时器支持范围内的正数。 */
4
5
  interval: number;
6
+ /** 等待 response 的超时时间(毫秒);未配置 response 时不启用应答超时。 */
5
7
  timeout?: number;
8
+ /** 服务端心跳响应内容,可配置一个或多个精确匹配值。 */
6
9
  response?: string | string[];
7
10
  };
8
11
  export type RealtimeSocketReconnectOptions = {
@@ -37,7 +40,9 @@ export declare class RealtimeSocketClient<T = unknown> {
37
40
  private reconnectAttempts;
38
41
  private manualClosed;
39
42
  private started;
40
- private lastHeartbeatAck;
43
+ private opening;
44
+ private openVersion;
45
+ private heartbeatSequence;
41
46
  constructor(options: RealtimeSocketClientOptions<T>);
42
47
  /** 获取当前连接状态,供业务显示或调试兜底使用。 */
43
48
  getState(): RealtimeSocketState;
@@ -53,13 +58,19 @@ export declare class RealtimeSocketClient<T = unknown> {
53
58
  private handleMessage;
54
59
  private handleClose;
55
60
  private handleError;
61
+ /** 启动单实例心跳;等待应答期间不重复发送,避免 interval 与 timeout 竞争。 */
56
62
  private startHeartbeat;
63
+ /** 心跳发送或应答超时后,仅关闭当前连接并进入既有重连流程。 */
64
+ private handleHeartbeatFailure;
57
65
  private scheduleReconnect;
58
66
  private getReconnectDelay;
59
67
  private handleOnline;
60
68
  private handleOffline;
61
69
  private setState;
62
70
  private closeSocket;
71
+ private cancelPendingOpen;
72
+ private isCurrentOpen;
73
+ private isCurrentSocket;
63
74
  private clearTimers;
64
75
  private clearHeartbeatTimers;
65
76
  private clearHeartbeatTimeoutTimer;