@jhh96/light-app-bridge 1.0.6 → 1.1.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.
@@ -39,6 +39,16 @@ export interface BridgeOptions {
39
39
  timeout?: number;
40
40
  /** 握手超时(ms),默认 30000。仅 plugin 角色生效;lightapp 端持续等待,不超时 */
41
41
  handshakeTimeout?: number;
42
+ /**
43
+ * 调试模式:开启后在控制台打印完整通信轨迹,便于排查 plugin ↔ lightapp
44
+ * 联调问题。覆盖:
45
+ * - 构造(角色/配置)、握手(hello/ack/连接建立/超时/重连)
46
+ * - 发送请求(send data + id)、底层投递(目标 webContentsId + 信封)
47
+ * - 收到消息(type/id/from/data)、响应返回(res 数据/超时)
48
+ * - handler 异常、销毁
49
+ * 大 payload 截断到 500 字符防刷屏。
50
+ */
51
+ debug?: boolean;
42
52
  }
43
53
  /** send 单次调用选项 */
44
54
  export interface SendOptions {
@@ -72,12 +82,16 @@ export default class LightAppBridge {
72
82
  private _listenerReady;
73
83
  private _connectFailed;
74
84
  private _destroyed;
85
+ private _debug;
86
+ private _helloCount;
75
87
  /**
76
88
  * @param role 角色,省略时按 window.worklink.plugin 是否存在自动探测
77
89
  * @param options 超时配置
78
90
  * @throws 依赖未就绪时抛出(window.worklink;监听后端可稍后出现,不算构造失败)
79
91
  */
80
92
  constructor(role?: BridgeRole, options?: BridgeOptions);
93
+ /** debug 日志(options.debug 开启时打印,前缀带角色便于双端对照) */
94
+ private _log;
81
95
  /** 校验依赖是否就绪,缺失抛出明确异常 */
82
96
  private _checkDeps;
83
97
  /** 绑定消息监听:优先 waltz;无 waltz 时定义/包装 window.handleMessageFromNative */
@@ -26,7 +26,21 @@ const PROTOCOL_VERSION = 1; // 协议版本号
26
26
  const DEFAULT_TIMEOUT = 3000; // send 默认超时(ms)
27
27
  const DEFAULT_HANDSHAKE_TIMEOUT = 30000; // 握手超时(ms)
28
28
  const HELLO_RETRY_INTERVAL = 1000; // 插件 hello 重试间隔(ms)
29
+ const DEBUG_PAYLOAD_LIMIT = 500; // debug 日志 payload 截断长度
29
30
  const genId = () => 'r_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 7);
31
+ /** debug 日志用:安全序列化 payload,超长截断 */
32
+ function debugPayload(data) {
33
+ let s;
34
+ try {
35
+ s = typeof data === 'string' ? data : JSON.stringify(data);
36
+ }
37
+ catch {
38
+ s = String(data);
39
+ }
40
+ if (s === undefined)
41
+ s = 'undefined';
42
+ return s.length > DEBUG_PAYLOAD_LIMIT ? s.slice(0, DEBUG_PAYLOAD_LIMIT) + `…(截断,共${s.length}字符)` : s;
43
+ }
30
44
  /** 判断是否为本 SDK 的消息(按 __sdk 标识过滤) */
31
45
  const isBridgeMsg = (msg) => !!(msg && typeof msg === 'object' && msg.__sdk === SDK_ID);
32
46
  /** 创建一个可外部 resolve 的 Promise */
@@ -165,6 +179,7 @@ export default class LightAppBridge {
165
179
  this._listenerReady = null;
166
180
  this._connectFailed = false;
167
181
  this._destroyed = false;
182
+ this._helloCount = 0;
168
183
  let r = role === 'plugin' || role === 'lightapp' ? role : 'lightapp';
169
184
  if (role !== 'plugin' && role !== 'lightapp') {
170
185
  const wl = window.worklink;
@@ -173,6 +188,11 @@ export default class LightAppBridge {
173
188
  this.role = r;
174
189
  this.timeout = options.timeout != null ? options.timeout : DEFAULT_TIMEOUT;
175
190
  this.handshakeTimeout = options.handshakeTimeout != null ? options.handshakeTimeout : DEFAULT_HANDSHAKE_TIMEOUT;
191
+ this._debug = !!options.debug;
192
+ this._log('构造: role=' + r + ', timeout=' + this.timeout +
193
+ ', handshakeTimeout=' + this.handshakeTimeout +
194
+ ', 监听后端=' + (hasWaltz() ? 'waltz' : 'handleMessageFromNative') +
195
+ ', 自身id=' + this.getId());
176
196
  // 连接 deferred:构造时即建立,保证轻应用收到 hello 也能 resolve(无需显式 connect)
177
197
  this._connectDeferred = deferred();
178
198
  this._connectPromise = this._connectDeferred.promise.then((peerId) => {
@@ -183,6 +203,12 @@ export default class LightAppBridge {
183
203
  this._startListener(); // 绑定消息监听(waltz 或定义 handleMessageFromNative)
184
204
  this.connect(); // 构造即自动发起握手(内部会等监听就绪)
185
205
  }
206
+ /** debug 日志(options.debug 开启时打印,前缀带角色便于双端对照) */
207
+ _log(...args) {
208
+ if (!this._debug)
209
+ return;
210
+ console.log(`[LightAppBridge:${this.role}]`, ...args);
211
+ }
186
212
  /** 校验依赖是否就绪,缺失抛出明确异常 */
187
213
  _checkDeps() {
188
214
  const w = window;
@@ -218,8 +244,12 @@ export default class LightAppBridge {
218
244
  _onMessage(msg) {
219
245
  const envelope = msg.envelope;
220
246
  const fromId = msg.fromWebContentsId;
221
- if (!isBridgeMsg(envelope))
247
+ if (!isBridgeMsg(envelope)) {
248
+ this._log('recv← 忽略非本SDK消息: from=' + fromId);
222
249
  return;
250
+ }
251
+ this._log('recv← type=' + envelope.type + ' id=' + envelope.id +
252
+ ' from=' + fromId + ' data=' + debugPayload(envelope.data));
223
253
  switch (envelope.type) {
224
254
  case 'hello':
225
255
  this._onHello(fromId);
@@ -316,12 +346,15 @@ export default class LightAppBridge {
316
346
  if (this._destroyed)
317
347
  return;
318
348
  this._connectFailed = true;
349
+ this._log('✗ 握手失败: ' + (e && e.message ? e.message : String(e)));
319
350
  this._connectDeferred.reject(e instanceof Error ? e : new Error(String(e)));
320
351
  }
321
352
  /** 发送 hello(携带自身 webContentsId) */
322
353
  _sendHello() {
323
354
  if (this._target == null)
324
355
  return;
356
+ this._helloCount++;
357
+ this._log('hello→ 目标=' + this._target + (this._helloCount > 1 ? ' (重试#' + this._helloCount + ')' : ''));
325
358
  this._send(this._target, this._envelope('hello', { from: this.getId() }));
326
359
  }
327
360
  /** 收到 hello(轻应用侧):记录对端、回 ack、完成握手 */
@@ -347,6 +380,7 @@ export default class LightAppBridge {
347
380
  }
348
381
  _onConnected(peerId) {
349
382
  this._connected = true;
383
+ this._log('✓ 连接建立: 对端=' + peerId + (this._helloCount > 1 ? ' (hello共' + this._helloCount + '次)' : ''));
350
384
  this._clearHelloTimer();
351
385
  if (this._handshakeTimer) {
352
386
  clearTimeout(this._handshakeTimer);
@@ -399,19 +433,24 @@ export default class LightAppBridge {
399
433
  Promise.allSettled(results).then((settled) => {
400
434
  for (const s of settled) {
401
435
  if (s.status === 'fulfilled' && s.value !== undefined) {
436
+ this._log('res→ id=' + id + ' data=' + debugPayload(s.value));
402
437
  this._send(this._peer, this._envelope('res', s.value, id));
403
438
  return;
404
439
  }
405
440
  }
441
+ this._log('✗ req 无可回复值(回调全空/异常): id=' + id);
406
442
  });
407
443
  }
408
444
  /** 收到 res:按 id 唤醒等待中的 send */
409
445
  _serveRes(envelope) {
410
446
  const p = this._pending.get(envelope.id);
411
- if (!p)
447
+ if (!p) {
448
+ this._log('recv← res 无等待者(可能已超时): id=' + envelope.id);
412
449
  return;
450
+ }
413
451
  clearTimeout(p.timer);
414
452
  this._pending.delete(envelope.id);
453
+ this._log('✓ 收到响应 id=' + envelope.id + ' data=' + debugPayload(envelope.data));
415
454
  p.resolve(envelope.data);
416
455
  }
417
456
  /** 底层发送:把信封投递到指定 webContentsId */
@@ -445,10 +484,12 @@ export default class LightAppBridge {
445
484
  return this.ready().then((targetId) => {
446
485
  const id = genId();
447
486
  const envelope = this._envelope('req', data, id);
487
+ this._log('send→ id=' + id + ' 目标=' + targetId + ' data=' + debugPayload(data));
448
488
  return new Promise((resolve, reject) => {
449
489
  const timer = setTimeout(() => {
450
490
  if (this._pending.has(id)) {
451
491
  this._pending.delete(id);
492
+ this._log('✗ 超时 id=' + id + ' (' + timeout + 'ms 无响应)');
452
493
  reject(new Error(`请求超时 (${timeout}ms)`));
453
494
  }
454
495
  }, timeout);
@@ -481,6 +522,7 @@ export default class LightAppBridge {
481
522
  if (this._destroyed)
482
523
  return;
483
524
  this._destroyed = true;
525
+ this._log('销毁实例: 未完成请求=' + this._pending.size);
484
526
  if (this._unlisten) {
485
527
  try {
486
528
  this._unlisten();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jhh96/light-app-bridge",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "招商随行(WorkLink)插件窗口(plugin)与轻应用窗口(lightapp)之间的双向通信 SDK",
6
6
  "main": "./dist/index.js",