@jhh96/light-app-bridge 1.2.0 → 1.3.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.
- package/dist/index.d.ts +1 -1
- package/dist/lightAppBridge.d.ts +41 -0
- package/dist/lightAppBridge.js +63 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { default } from './lightAppBridge';
|
|
2
2
|
export { createBridge } from './lightAppBridge';
|
|
3
|
-
export type { BridgeRole, BindMode, EnvelopeType, Envelope, BridgeOptions, SendOptions, MessageHandler } from './lightAppBridge';
|
|
3
|
+
export type { BridgeRole, BindMode, ReportMode, EnvelopeType, Envelope, BridgeOptions, SendOptions, MessageHandler } from './lightAppBridge';
|
package/dist/lightAppBridge.d.ts
CHANGED
|
@@ -30,6 +30,17 @@ export type BridgeRole = 'plugin' | 'lightapp';
|
|
|
30
30
|
* 向新窗口探测握手(成功即切换绑定;失败——如未集成 SDK——保持旧绑定)。
|
|
31
31
|
*/
|
|
32
32
|
export type BindMode = 'fixed' | 'dynamic';
|
|
33
|
+
/**
|
|
34
|
+
* 指令执行结果的上报模式(轻应用角色语义声明,默认 'plugin'):
|
|
35
|
+
* - plugin 默认。轻应用不在本窗口回传 ai-controller,执行结果随 reply 返回
|
|
36
|
+
* 插件窗口,由插件统一上报。reply 无需额外字段。
|
|
37
|
+
* - self 轻应用业务自行 POST ai-controller/callback(如需 AI 闭环),
|
|
38
|
+
* 并在 onMessage 的 reply 上带 result_reported: true,
|
|
39
|
+
* 插件据此跳过补报,避免双重上报。
|
|
40
|
+
* 纯语义声明:SDK 不执行上报,读取方是插件侧业务代码(经 reply 字段判定),
|
|
41
|
+
* 两 SDK 间零依赖。
|
|
42
|
+
*/
|
|
43
|
+
export type ReportMode = 'plugin' | 'self';
|
|
33
44
|
/** 信封类型 */
|
|
34
45
|
export type EnvelopeType = 'hello' | 'ack' | 'req' | 'res' | 'ping' | 'pong';
|
|
35
46
|
/** 消息信封:所有跨窗口通信的统一包装 */
|
|
@@ -51,6 +62,13 @@ export interface BridgeOptions {
|
|
|
51
62
|
* dynamic:轮询 getContentContext 跟随当前激活的轻应用窗口切换绑定。
|
|
52
63
|
*/
|
|
53
64
|
bindMode?: BindMode;
|
|
65
|
+
/**
|
|
66
|
+
* 结果上报模式(轻应用角色语义声明),默认 'plugin':
|
|
67
|
+
* 'plugin'=结果交插件统一上报(reply 无需额外字段);
|
|
68
|
+
* 'self'=业务自行上报并在 reply 带 result_reported: true。
|
|
69
|
+
* SDK 不执行上报,仅存为实例属性 reportMode 供业务读取。
|
|
70
|
+
*/
|
|
71
|
+
reportMode?: ReportMode;
|
|
54
72
|
/** dynamic 模式轮询 getContentContext 的间隔(ms),默认 2000 */
|
|
55
73
|
dynamicPollInterval?: number;
|
|
56
74
|
/** dynamic 模式迁移探测窗口:向新窗口发 hello 等 ack 的时长(ms),默认 3000 */
|
|
@@ -94,6 +112,7 @@ export default class LightAppBridge {
|
|
|
94
112
|
timeout: number;
|
|
95
113
|
handshakeTimeout: number;
|
|
96
114
|
bindMode: BindMode;
|
|
115
|
+
reportMode: ReportMode;
|
|
97
116
|
dynamicPollInterval: number;
|
|
98
117
|
migrateProbeTimeout: number;
|
|
99
118
|
pingInterval: number;
|
|
@@ -139,6 +158,28 @@ export default class LightAppBridge {
|
|
|
139
158
|
constructor(role?: BridgeRole, options?: BridgeOptions);
|
|
140
159
|
/** debug 日志(options.debug 开启时打印,前缀带角色便于双端对照) */
|
|
141
160
|
private _log;
|
|
161
|
+
/**
|
|
162
|
+
* debug 模式下在 window 挂载控制台测试方法(挂在单一入口 __lightAppBridge 下,
|
|
163
|
+
* destroy 时注销):
|
|
164
|
+
*
|
|
165
|
+
* __lightAppBridge.send(data, timeout?) —— 以本实例身份向对端发一条请求,返回 Promise。
|
|
166
|
+
* 等价于业务代码里的 bridge.send(...)。
|
|
167
|
+
* await __lightAppBridge.send({ action: 'ping' })
|
|
168
|
+
* await __lightAppBridge.send({ action: 'scroll.to', payload: {...} }, 5000)
|
|
169
|
+
*
|
|
170
|
+
* __lightAppBridge.inject(type, data?, fromId?, id?) —— 模拟对端来一条消息,直接喂给
|
|
171
|
+
* 本实例的消息分发入口(绕过原生投递层),无需真实对端窗口即可测试收发逻辑。
|
|
172
|
+
* type 取信封类型:'hello' | 'ack' | 'req' | 'res' | 'ping'
|
|
173
|
+
* __lightAppBridge.inject('ping') // 看本端自动回 pong
|
|
174
|
+
* __lightAppBridge.inject('req', { action: 'test' }) // 触发本端 onMessage handler
|
|
175
|
+
* __lightAppBridge.inject('hello', null, 42) // 模拟 webContentsId=42 的对端握手
|
|
176
|
+
* __lightAppBridge.inject('res', {ok:1}, 77, reqId) // 回 res:第 4 参传原请求 id 配对唤醒
|
|
177
|
+
*
|
|
178
|
+
* 多实例同时开启 debug 时后注册者覆盖前者(控制台操作的是最后创建的实例)。
|
|
179
|
+
* 不挂实例本身(避免控制台误触内部状态)。
|
|
180
|
+
*/
|
|
181
|
+
private _registerDebugHelpers;
|
|
182
|
+
private _debugCleanup;
|
|
142
183
|
/** 校验依赖是否就绪,缺失抛出明确异常 */
|
|
143
184
|
private _checkDeps;
|
|
144
185
|
/** 绑定消息监听:优先 waltz;无 waltz 时定义/包装 window.handleMessageFromNative */
|
package/dist/lightAppBridge.js
CHANGED
|
@@ -202,6 +202,7 @@ export default class LightAppBridge {
|
|
|
202
202
|
this._probeOk = false; // 兜底探测是否收到 ack
|
|
203
203
|
this._probeTimers = []; // 防 destroy 后悬挂
|
|
204
204
|
this._disconnectCbs = [];
|
|
205
|
+
this._debugCleanup = null;
|
|
205
206
|
let r = role === 'plugin' || role === 'lightapp' ? role : 'lightapp';
|
|
206
207
|
if (role !== 'plugin' && role !== 'lightapp') {
|
|
207
208
|
const wl = window.worklink;
|
|
@@ -211,6 +212,7 @@ export default class LightAppBridge {
|
|
|
211
212
|
this.timeout = options.timeout != null ? options.timeout : DEFAULT_TIMEOUT;
|
|
212
213
|
this.handshakeTimeout = options.handshakeTimeout != null ? options.handshakeTimeout : DEFAULT_HANDSHAKE_TIMEOUT;
|
|
213
214
|
this.bindMode = options.bindMode === 'dynamic' ? 'dynamic' : DEFAULT_BIND_MODE;
|
|
215
|
+
this.reportMode = options.reportMode === 'self' ? 'self' : 'plugin';
|
|
214
216
|
this.dynamicPollInterval = options.dynamicPollInterval != null ? options.dynamicPollInterval : DEFAULT_DYNAMIC_POLL_INTERVAL;
|
|
215
217
|
this.migrateProbeTimeout = options.migrateProbeTimeout != null ? options.migrateProbeTimeout : DEFAULT_MIGRATE_PROBE_TIMEOUT;
|
|
216
218
|
this.pingInterval = options.pingInterval != null ? options.pingInterval : DEFAULT_PING_INTERVAL;
|
|
@@ -232,6 +234,7 @@ export default class LightAppBridge {
|
|
|
232
234
|
});
|
|
233
235
|
this._checkDeps(); // 依赖校验,缺失直接抛异常
|
|
234
236
|
this._startListener(); // 绑定消息监听(waltz 或定义 handleMessageFromNative)
|
|
237
|
+
this._registerDebugHelpers(); // debug 模式:注册控制台测试方法
|
|
235
238
|
this.connect(); // 构造即自动发起握手(内部会等监听就绪)
|
|
236
239
|
}
|
|
237
240
|
/** debug 日志(options.debug 开启时打印,前缀带角色便于双端对照) */
|
|
@@ -240,6 +243,58 @@ export default class LightAppBridge {
|
|
|
240
243
|
return;
|
|
241
244
|
console.log(`[LightAppBridge:${this.role}]`, ...args);
|
|
242
245
|
}
|
|
246
|
+
// —— debug 控制台测试方法(options.debug 开启时挂 window)—— //
|
|
247
|
+
/**
|
|
248
|
+
* debug 模式下在 window 挂载控制台测试方法(挂在单一入口 __lightAppBridge 下,
|
|
249
|
+
* destroy 时注销):
|
|
250
|
+
*
|
|
251
|
+
* __lightAppBridge.send(data, timeout?) —— 以本实例身份向对端发一条请求,返回 Promise。
|
|
252
|
+
* 等价于业务代码里的 bridge.send(...)。
|
|
253
|
+
* await __lightAppBridge.send({ action: 'ping' })
|
|
254
|
+
* await __lightAppBridge.send({ action: 'scroll.to', payload: {...} }, 5000)
|
|
255
|
+
*
|
|
256
|
+
* __lightAppBridge.inject(type, data?, fromId?, id?) —— 模拟对端来一条消息,直接喂给
|
|
257
|
+
* 本实例的消息分发入口(绕过原生投递层),无需真实对端窗口即可测试收发逻辑。
|
|
258
|
+
* type 取信封类型:'hello' | 'ack' | 'req' | 'res' | 'ping'
|
|
259
|
+
* __lightAppBridge.inject('ping') // 看本端自动回 pong
|
|
260
|
+
* __lightAppBridge.inject('req', { action: 'test' }) // 触发本端 onMessage handler
|
|
261
|
+
* __lightAppBridge.inject('hello', null, 42) // 模拟 webContentsId=42 的对端握手
|
|
262
|
+
* __lightAppBridge.inject('res', {ok:1}, 77, reqId) // 回 res:第 4 参传原请求 id 配对唤醒
|
|
263
|
+
*
|
|
264
|
+
* 多实例同时开启 debug 时后注册者覆盖前者(控制台操作的是最后创建的实例)。
|
|
265
|
+
* 不挂实例本身(避免控制台误触内部状态)。
|
|
266
|
+
*/
|
|
267
|
+
_registerDebugHelpers() {
|
|
268
|
+
if (!this._debug)
|
|
269
|
+
return;
|
|
270
|
+
const w = window;
|
|
271
|
+
const sendFn = (data, timeout) => {
|
|
272
|
+
// eslint-disable-next-line no-console
|
|
273
|
+
console.log(`[LightAppBridge:${this.role}] send→`, data);
|
|
274
|
+
return this.send(data, timeout != null ? { timeout } : undefined);
|
|
275
|
+
};
|
|
276
|
+
const injectFn = (type, data, fromId, id) => {
|
|
277
|
+
const envelope = this._envelope(type, data != null ? data : {}, id || genId() // res 场景必须传原请求 id 才能配对唤醒(未传则生成新 id,作为陌生 res 被忽略)
|
|
278
|
+
);
|
|
279
|
+
// eslint-disable-next-line no-console
|
|
280
|
+
console.log(`[LightAppBridge:${this.role}] inject←`, envelope);
|
|
281
|
+
this._onMessage({ envelope, fromWebContentsId: fromId != null ? fromId : 0 });
|
|
282
|
+
};
|
|
283
|
+
const facade = { send: sendFn, inject: injectFn };
|
|
284
|
+
const prev = w.__lightAppBridge; // 多实例 debug:保留被覆盖者的清理引用链
|
|
285
|
+
w.__lightAppBridge = facade;
|
|
286
|
+
// eslint-disable-next-line no-console
|
|
287
|
+
console.info(`[LightAppBridge:${this.role}] debug 方法已挂载: ` +
|
|
288
|
+
'await __lightAppBridge.send(data, timeout?) 发请求 / ' +
|
|
289
|
+
'__lightAppBridge.inject(type, data?, fromId?, id?) 模拟来消息');
|
|
290
|
+
this._debugCleanup = () => {
|
|
291
|
+
// 仅当仍是自己挂的 facade 才清理,避免误删后建实例的挂载
|
|
292
|
+
if (w.__lightAppBridge === facade)
|
|
293
|
+
delete w.__lightAppBridge;
|
|
294
|
+
else
|
|
295
|
+
w.__lightAppBridge = prev;
|
|
296
|
+
};
|
|
297
|
+
}
|
|
243
298
|
/** 校验依赖是否就绪,缺失抛出明确异常 */
|
|
244
299
|
_checkDeps() {
|
|
245
300
|
const w = window;
|
|
@@ -821,6 +876,14 @@ export default class LightAppBridge {
|
|
|
821
876
|
catch { /* ignore */ }
|
|
822
877
|
this._unlisten = null;
|
|
823
878
|
}
|
|
879
|
+
// 注销 debug 控制台测试方法
|
|
880
|
+
if (this._debugCleanup) {
|
|
881
|
+
try {
|
|
882
|
+
this._debugCleanup();
|
|
883
|
+
}
|
|
884
|
+
catch { /* ignore */ }
|
|
885
|
+
this._debugCleanup = null;
|
|
886
|
+
}
|
|
824
887
|
this._clearHelloTimer();
|
|
825
888
|
this._stopDynamicPoll();
|
|
826
889
|
this._stopPing();
|