@webview-bridge/web 1.5.1-rc.0 → 1.5.1-rc.1
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/commonjs/index.cjs +166 -145
- package/dist/module/index.mjs +166 -145
- package/dist/typescript/packages/web/src/internal/bridgeInstance.d.ts +18 -0
- package/dist/typescript/packages/web/src/internal/linkBridgeStore.d.ts +2 -1
- package/dist/typescript/shared/util/src/createEvents.d.ts +2 -1
- package/package.json +1 -1
package/dist/commonjs/index.cjs
CHANGED
|
@@ -33,6 +33,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
33
33
|
return to;
|
|
34
34
|
};
|
|
35
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
|
+
var __publicField = (obj, key, value) => {
|
|
37
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
38
|
+
return value;
|
|
39
|
+
};
|
|
36
40
|
var __async = (__this, __arguments, generator) => {
|
|
37
41
|
return new Promise((resolve, reject) => {
|
|
38
42
|
var fulfilled = (value) => {
|
|
@@ -98,7 +102,7 @@ var createEvents = () => ({
|
|
|
98
102
|
}
|
|
99
103
|
});
|
|
100
104
|
var createResolver = ({
|
|
101
|
-
emitter
|
|
105
|
+
emitter,
|
|
102
106
|
evaluate,
|
|
103
107
|
eventId,
|
|
104
108
|
failHandler = false,
|
|
@@ -106,7 +110,7 @@ var createResolver = ({
|
|
|
106
110
|
onFallback
|
|
107
111
|
}) => {
|
|
108
112
|
return new Promise((resolve, reject) => {
|
|
109
|
-
const unbind =
|
|
113
|
+
const unbind = emitter.on(
|
|
110
114
|
`${methodName}-${eventId}`,
|
|
111
115
|
(data, throwOccurred) => {
|
|
112
116
|
unbind();
|
|
@@ -211,18 +215,8 @@ var timeout = (ms, throwOnError = true) => {
|
|
|
211
215
|
});
|
|
212
216
|
};
|
|
213
217
|
|
|
214
|
-
// src/internal/emitter.ts
|
|
215
|
-
var emitter = createEvents();
|
|
216
|
-
|
|
217
218
|
// src/internal/linkBridgeStore.ts
|
|
218
|
-
var linkBridgeStore = (initialState = {}) => {
|
|
219
|
-
var _a;
|
|
220
|
-
if (!window.ReactNativeWebView) {
|
|
221
|
-
console.warn("[WebViewBridge] Not in a WebView environment");
|
|
222
|
-
}
|
|
223
|
-
if (!window.nativeEmitter) {
|
|
224
|
-
window.nativeEmitter = emitter;
|
|
225
|
-
}
|
|
219
|
+
var linkBridgeStore = (emitter, initialState = {}, nativeInitialState = {}) => {
|
|
226
220
|
const getState = () => state;
|
|
227
221
|
const setState = (newState) => {
|
|
228
222
|
const _newState = __spreadValues(__spreadValues({}, state), removeUndefinedKeys(newState));
|
|
@@ -236,22 +230,7 @@ var linkBridgeStore = (initialState = {}) => {
|
|
|
236
230
|
emitter.on("bridgeStateChange", (data) => {
|
|
237
231
|
setState(data);
|
|
238
232
|
});
|
|
239
|
-
|
|
240
|
-
var _a2;
|
|
241
|
-
if (document.visibilityState === "visible") {
|
|
242
|
-
(_a2 = window.ReactNativeWebView) == null ? void 0 : _a2.postMessage(
|
|
243
|
-
JSON.stringify({
|
|
244
|
-
type: "getBridgeState"
|
|
245
|
-
})
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
(_a = window.ReactNativeWebView) == null ? void 0 : _a.postMessage(
|
|
250
|
-
JSON.stringify({
|
|
251
|
-
type: "getBridgeState"
|
|
252
|
-
})
|
|
253
|
-
);
|
|
254
|
-
let state = __spreadValues(__spreadValues({}, initialState), window.__bridgeInitialState__);
|
|
233
|
+
let state = __spreadValues(__spreadValues({}, initialState), nativeInitialState);
|
|
255
234
|
const listeners = /* @__PURE__ */ new Set();
|
|
256
235
|
const emitChange = (newState, prevState) => {
|
|
257
236
|
for (const listener of listeners) {
|
|
@@ -268,47 +247,160 @@ var linkBridgeStore = (initialState = {}) => {
|
|
|
268
247
|
};
|
|
269
248
|
};
|
|
270
249
|
|
|
271
|
-
// src/
|
|
272
|
-
var
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
250
|
+
// src/internal/bridgeInstance.ts
|
|
251
|
+
var BridgeInstance = class {
|
|
252
|
+
constructor(emitter, bridgeMethods, options) {
|
|
253
|
+
this.emitter = emitter;
|
|
254
|
+
this.bridgeMethods = bridgeMethods;
|
|
255
|
+
this.options = options;
|
|
256
|
+
__publicField(this, "defaultTimeoutMs", 2e3);
|
|
257
|
+
__publicField(this, "$proxy");
|
|
258
|
+
this.$proxy = this.hydrate(bridgeMethods);
|
|
259
|
+
}
|
|
260
|
+
postMessage(type, body) {
|
|
261
|
+
var _a;
|
|
262
|
+
(_a = window.ReactNativeWebView) == null ? void 0 : _a.postMessage(
|
|
263
|
+
JSON.stringify(
|
|
264
|
+
body ? {
|
|
265
|
+
type,
|
|
266
|
+
body
|
|
267
|
+
} : {
|
|
268
|
+
type
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
createNativeMethod(methodName, throwOnError, timeoutMs, onFallback) {
|
|
274
|
+
return (...args) => {
|
|
275
|
+
const eventId = createRandomId();
|
|
276
|
+
return Promise.race(
|
|
277
|
+
[
|
|
278
|
+
createResolver({
|
|
279
|
+
emitter: this.emitter,
|
|
280
|
+
methodName,
|
|
281
|
+
eventId,
|
|
282
|
+
evaluate: () => {
|
|
283
|
+
this.postMessage("bridge", {
|
|
291
284
|
method: methodName,
|
|
292
285
|
eventId,
|
|
293
286
|
args
|
|
294
|
-
}
|
|
295
|
-
}
|
|
287
|
+
});
|
|
288
|
+
},
|
|
289
|
+
onFallback: () => {
|
|
290
|
+
onFallback == null ? void 0 : onFallback(methodName, args);
|
|
291
|
+
},
|
|
292
|
+
failHandler: throwOnError && new NativeMethodError(methodName)
|
|
293
|
+
}),
|
|
294
|
+
timeoutMs > 0 && timeout(timeoutMs, throwOnError)
|
|
295
|
+
].filter(Boolean)
|
|
296
|
+
);
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
willMethodThrowOnError(methodName) {
|
|
300
|
+
const { throwOnError } = this.options;
|
|
301
|
+
return throwOnError === true || Array.isArray(throwOnError) && throwOnError.includes(methodName);
|
|
302
|
+
}
|
|
303
|
+
createLoose(initialState) {
|
|
304
|
+
const { timeout: timeoutMs = this.defaultTimeoutMs, onFallback } = this.options;
|
|
305
|
+
return new Proxy(initialState, {
|
|
306
|
+
get: (target, methodName) => {
|
|
307
|
+
if (methodName in target && !["isWebViewBridgeAvailable", "isNativeMethodAvailable"].includes(
|
|
308
|
+
methodName
|
|
309
|
+
)) {
|
|
310
|
+
return target[methodName];
|
|
311
|
+
}
|
|
312
|
+
return this.createNativeMethod(
|
|
313
|
+
methodName,
|
|
314
|
+
this.willMethodThrowOnError(methodName),
|
|
315
|
+
timeoutMs,
|
|
316
|
+
onFallback
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
hydrate(bridgeMethods, nativeInitialState = {}) {
|
|
322
|
+
var _a;
|
|
323
|
+
const {
|
|
324
|
+
timeout: timeoutMs = this.defaultTimeoutMs,
|
|
325
|
+
onFallback,
|
|
326
|
+
onReady
|
|
327
|
+
} = this.options;
|
|
328
|
+
const initialState = bridgeMethods.reduce(
|
|
329
|
+
(acc, methodName) => {
|
|
330
|
+
return __spreadProps(__spreadValues({}, acc), {
|
|
331
|
+
[methodName]: this.createNativeMethod(
|
|
332
|
+
methodName,
|
|
333
|
+
this.willMethodThrowOnError(methodName),
|
|
334
|
+
timeoutMs,
|
|
335
|
+
onFallback
|
|
336
|
+
)
|
|
337
|
+
});
|
|
338
|
+
},
|
|
339
|
+
{}
|
|
340
|
+
);
|
|
341
|
+
const loose = this.createLoose(initialState);
|
|
342
|
+
const store = linkBridgeStore(
|
|
343
|
+
this.emitter,
|
|
344
|
+
initialState,
|
|
345
|
+
nativeInitialState
|
|
346
|
+
);
|
|
347
|
+
Object.assign(initialState, {
|
|
348
|
+
loose,
|
|
349
|
+
store,
|
|
350
|
+
isWebViewBridgeAvailable: Boolean(window.ReactNativeWebView) && bridgeMethods.length > 0,
|
|
351
|
+
isNativeMethodAvailable(methodName) {
|
|
352
|
+
return typeof methodName === "string" && Boolean(window.ReactNativeWebView) && bridgeMethods.includes(methodName);
|
|
353
|
+
},
|
|
354
|
+
addEventListener: (eventName, listener) => {
|
|
355
|
+
return this.emitter.on(`postMessage/${String(eventName)}`, listener);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
document.addEventListener("visibilitychange", () => {
|
|
359
|
+
if (document.visibilityState === "visible") {
|
|
360
|
+
this.postMessage("getBridgeState");
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
this.postMessage("getBridgeState");
|
|
364
|
+
const proxy = new Proxy(initialState, {
|
|
365
|
+
get: (target, methodName) => {
|
|
366
|
+
if (methodName in target) {
|
|
367
|
+
return target[methodName];
|
|
368
|
+
}
|
|
369
|
+
this.postMessage("fallback", {
|
|
370
|
+
method: methodName
|
|
371
|
+
});
|
|
372
|
+
if (this.willMethodThrowOnError(methodName)) {
|
|
373
|
+
return (...args) => {
|
|
374
|
+
onFallback == null ? void 0 : onFallback(methodName, args);
|
|
375
|
+
return Promise.reject(new MethodNotFoundError(methodName));
|
|
376
|
+
};
|
|
377
|
+
} else {
|
|
378
|
+
console.warn(
|
|
379
|
+
`[WebViewBridge] ${methodName} is not defined, using fallback.`
|
|
296
380
|
);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
]
|
|
305
|
-
|
|
381
|
+
}
|
|
382
|
+
return () => Promise.resolve();
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
for (const [eventName, ...args] of (_a = window.nativeBatchedEvents) != null ? _a : []) {
|
|
386
|
+
this.emitter.emit(eventName, ...args);
|
|
387
|
+
}
|
|
388
|
+
window.nativeBatchedEvents = [];
|
|
389
|
+
onReady == null ? void 0 : onReady(proxy);
|
|
390
|
+
this.$proxy = proxy;
|
|
391
|
+
return proxy;
|
|
392
|
+
}
|
|
393
|
+
get proxy() {
|
|
394
|
+
return this.$proxy;
|
|
395
|
+
}
|
|
306
396
|
};
|
|
397
|
+
|
|
398
|
+
// src/linkBridge.ts
|
|
307
399
|
var linkBridge = (options = {
|
|
308
400
|
timeout: 2e3,
|
|
309
401
|
throwOnError: false
|
|
310
402
|
}) => {
|
|
311
|
-
var _a
|
|
403
|
+
var _a;
|
|
312
404
|
if (typeof window === "undefined") {
|
|
313
405
|
return {
|
|
314
406
|
store: {
|
|
@@ -317,94 +409,23 @@ var linkBridge = (options = {
|
|
|
317
409
|
}
|
|
318
410
|
};
|
|
319
411
|
}
|
|
320
|
-
const {
|
|
321
|
-
timeout: timeoutMs = 2e3,
|
|
322
|
-
throwOnError = false,
|
|
323
|
-
onFallback,
|
|
324
|
-
onReady
|
|
325
|
-
} = options;
|
|
326
412
|
if (!window.ReactNativeWebView) {
|
|
327
413
|
console.warn("[WebViewBridge] Not in a WebView environment");
|
|
328
414
|
}
|
|
329
|
-
const
|
|
415
|
+
const emitter = createEvents();
|
|
330
416
|
if (!window.nativeEmitter) {
|
|
331
417
|
window.nativeEmitter = emitter;
|
|
332
418
|
}
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
methodName,
|
|
341
|
-
timeoutMs,
|
|
342
|
-
throwOnError: willMethodThrowOnError(methodName),
|
|
343
|
-
onFallback
|
|
344
|
-
})
|
|
345
|
-
});
|
|
346
|
-
},
|
|
347
|
-
{}
|
|
348
|
-
);
|
|
349
|
-
const loose = new Proxy(target, {
|
|
350
|
-
get: (target2, methodName) => {
|
|
351
|
-
if (methodName in target2 && !["isWebViewBridgeAvailable", "isNativeMethodAvailable"].includes(
|
|
352
|
-
methodName
|
|
353
|
-
)) {
|
|
354
|
-
return target2[methodName];
|
|
355
|
-
}
|
|
356
|
-
return createNativeMethod({
|
|
357
|
-
methodName,
|
|
358
|
-
timeoutMs,
|
|
359
|
-
throwOnError: willMethodThrowOnError(methodName),
|
|
360
|
-
onFallback
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
Object.assign(target, {
|
|
365
|
-
loose,
|
|
366
|
-
store: linkBridgeStore(target),
|
|
367
|
-
isWebViewBridgeAvailable: Boolean(window.ReactNativeWebView) && bridgeMethods.length > 0,
|
|
368
|
-
isNativeMethodAvailable(methodName) {
|
|
369
|
-
return typeof methodName === "string" && Boolean(window.ReactNativeWebView) && bridgeMethods.includes(methodName);
|
|
370
|
-
},
|
|
371
|
-
addEventListener: (eventName, listener) => {
|
|
372
|
-
return emitter.on(`postMessage/${String(eventName)}`, listener);
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
const proxy = new Proxy(target, {
|
|
376
|
-
get: (target2, methodName) => {
|
|
377
|
-
var _a2;
|
|
378
|
-
if (methodName in target2) {
|
|
379
|
-
return target2[methodName];
|
|
380
|
-
}
|
|
381
|
-
(_a2 = window.ReactNativeWebView) == null ? void 0 : _a2.postMessage(
|
|
382
|
-
JSON.stringify({
|
|
383
|
-
type: "fallback",
|
|
384
|
-
body: {
|
|
385
|
-
method: methodName
|
|
386
|
-
}
|
|
387
|
-
})
|
|
388
|
-
);
|
|
389
|
-
if (willMethodThrowOnError(methodName)) {
|
|
390
|
-
return (...args) => {
|
|
391
|
-
onFallback == null ? void 0 : onFallback(methodName, args);
|
|
392
|
-
Promise.reject(new MethodNotFoundError(methodName));
|
|
393
|
-
};
|
|
394
|
-
} else {
|
|
395
|
-
console.warn(
|
|
396
|
-
`[WebViewBridge] ${methodName} is not defined, using fallback.`
|
|
397
|
-
);
|
|
398
|
-
}
|
|
399
|
-
return () => Promise.resolve();
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
for (const [eventName, ...args] of (_b = window.nativeBatchedEvents) != null ? _b : []) {
|
|
403
|
-
emitter.emit(eventName, ...args);
|
|
419
|
+
const bridgeMethods = (_a = window.__bridgeMethods__) != null ? _a : [];
|
|
420
|
+
const instance = new BridgeInstance(emitter, bridgeMethods, options);
|
|
421
|
+
if (bridgeMethods.length === 0) {
|
|
422
|
+
const unsubscribe = emitter.on("hydrate", ({ bridgeMethods: bridgeMethods2 }) => {
|
|
423
|
+
instance.hydrate(bridgeMethods2);
|
|
424
|
+
unsubscribe();
|
|
425
|
+
});
|
|
404
426
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return proxy;
|
|
427
|
+
instance.hydrate(bridgeMethods);
|
|
428
|
+
return instance.proxy;
|
|
408
429
|
};
|
|
409
430
|
|
|
410
431
|
// src/linkNativeMethod.ts
|
|
@@ -423,8 +444,8 @@ var registerWebMethod = (bridge) => {
|
|
|
423
444
|
}
|
|
424
445
|
const bridgeEntries = Object.entries(bridge);
|
|
425
446
|
const bridgeNames = Object.keys(bridge);
|
|
426
|
-
const
|
|
427
|
-
window.webEmitter =
|
|
447
|
+
const emitter = createEvents();
|
|
448
|
+
window.webEmitter = emitter;
|
|
428
449
|
for (const [funcName, func] of bridgeEntries) {
|
|
429
450
|
const $func = (eventId, args) => __async(void 0, null, function* () {
|
|
430
451
|
var _a, _b;
|
|
@@ -445,7 +466,7 @@ var registerWebMethod = (bridge) => {
|
|
|
445
466
|
);
|
|
446
467
|
}
|
|
447
468
|
});
|
|
448
|
-
|
|
469
|
+
emitter.on(funcName, $func);
|
|
449
470
|
}
|
|
450
471
|
const register = () => {
|
|
451
472
|
var _a;
|
package/dist/module/index.mjs
CHANGED
|
@@ -17,6 +17,10 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
return a;
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __publicField = (obj, key, value) => {
|
|
21
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
22
|
+
return value;
|
|
23
|
+
};
|
|
20
24
|
var __async = (__this, __arguments, generator) => {
|
|
21
25
|
return new Promise((resolve, reject) => {
|
|
22
26
|
var fulfilled = (value) => {
|
|
@@ -71,7 +75,7 @@ var createEvents = () => ({
|
|
|
71
75
|
}
|
|
72
76
|
});
|
|
73
77
|
var createResolver = ({
|
|
74
|
-
emitter
|
|
78
|
+
emitter,
|
|
75
79
|
evaluate,
|
|
76
80
|
eventId,
|
|
77
81
|
failHandler = false,
|
|
@@ -79,7 +83,7 @@ var createResolver = ({
|
|
|
79
83
|
onFallback
|
|
80
84
|
}) => {
|
|
81
85
|
return new Promise((resolve, reject) => {
|
|
82
|
-
const unbind =
|
|
86
|
+
const unbind = emitter.on(
|
|
83
87
|
`${methodName}-${eventId}`,
|
|
84
88
|
(data, throwOccurred) => {
|
|
85
89
|
unbind();
|
|
@@ -184,18 +188,8 @@ var timeout = (ms, throwOnError = true) => {
|
|
|
184
188
|
});
|
|
185
189
|
};
|
|
186
190
|
|
|
187
|
-
// src/internal/emitter.ts
|
|
188
|
-
var emitter = createEvents();
|
|
189
|
-
|
|
190
191
|
// src/internal/linkBridgeStore.ts
|
|
191
|
-
var linkBridgeStore = (initialState = {}) => {
|
|
192
|
-
var _a;
|
|
193
|
-
if (!window.ReactNativeWebView) {
|
|
194
|
-
console.warn("[WebViewBridge] Not in a WebView environment");
|
|
195
|
-
}
|
|
196
|
-
if (!window.nativeEmitter) {
|
|
197
|
-
window.nativeEmitter = emitter;
|
|
198
|
-
}
|
|
192
|
+
var linkBridgeStore = (emitter, initialState = {}, nativeInitialState = {}) => {
|
|
199
193
|
const getState = () => state;
|
|
200
194
|
const setState = (newState) => {
|
|
201
195
|
const _newState = __spreadValues(__spreadValues({}, state), removeUndefinedKeys(newState));
|
|
@@ -209,22 +203,7 @@ var linkBridgeStore = (initialState = {}) => {
|
|
|
209
203
|
emitter.on("bridgeStateChange", (data) => {
|
|
210
204
|
setState(data);
|
|
211
205
|
});
|
|
212
|
-
|
|
213
|
-
var _a2;
|
|
214
|
-
if (document.visibilityState === "visible") {
|
|
215
|
-
(_a2 = window.ReactNativeWebView) == null ? void 0 : _a2.postMessage(
|
|
216
|
-
JSON.stringify({
|
|
217
|
-
type: "getBridgeState"
|
|
218
|
-
})
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
(_a = window.ReactNativeWebView) == null ? void 0 : _a.postMessage(
|
|
223
|
-
JSON.stringify({
|
|
224
|
-
type: "getBridgeState"
|
|
225
|
-
})
|
|
226
|
-
);
|
|
227
|
-
let state = __spreadValues(__spreadValues({}, initialState), window.__bridgeInitialState__);
|
|
206
|
+
let state = __spreadValues(__spreadValues({}, initialState), nativeInitialState);
|
|
228
207
|
const listeners = /* @__PURE__ */ new Set();
|
|
229
208
|
const emitChange = (newState, prevState) => {
|
|
230
209
|
for (const listener of listeners) {
|
|
@@ -241,47 +220,160 @@ var linkBridgeStore = (initialState = {}) => {
|
|
|
241
220
|
};
|
|
242
221
|
};
|
|
243
222
|
|
|
244
|
-
// src/
|
|
245
|
-
var
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
223
|
+
// src/internal/bridgeInstance.ts
|
|
224
|
+
var BridgeInstance = class {
|
|
225
|
+
constructor(emitter, bridgeMethods, options) {
|
|
226
|
+
this.emitter = emitter;
|
|
227
|
+
this.bridgeMethods = bridgeMethods;
|
|
228
|
+
this.options = options;
|
|
229
|
+
__publicField(this, "defaultTimeoutMs", 2e3);
|
|
230
|
+
__publicField(this, "$proxy");
|
|
231
|
+
this.$proxy = this.hydrate(bridgeMethods);
|
|
232
|
+
}
|
|
233
|
+
postMessage(type, body) {
|
|
234
|
+
var _a;
|
|
235
|
+
(_a = window.ReactNativeWebView) == null ? void 0 : _a.postMessage(
|
|
236
|
+
JSON.stringify(
|
|
237
|
+
body ? {
|
|
238
|
+
type,
|
|
239
|
+
body
|
|
240
|
+
} : {
|
|
241
|
+
type
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
createNativeMethod(methodName, throwOnError, timeoutMs, onFallback) {
|
|
247
|
+
return (...args) => {
|
|
248
|
+
const eventId = createRandomId();
|
|
249
|
+
return Promise.race(
|
|
250
|
+
[
|
|
251
|
+
createResolver({
|
|
252
|
+
emitter: this.emitter,
|
|
253
|
+
methodName,
|
|
254
|
+
eventId,
|
|
255
|
+
evaluate: () => {
|
|
256
|
+
this.postMessage("bridge", {
|
|
264
257
|
method: methodName,
|
|
265
258
|
eventId,
|
|
266
259
|
args
|
|
267
|
-
}
|
|
268
|
-
}
|
|
260
|
+
});
|
|
261
|
+
},
|
|
262
|
+
onFallback: () => {
|
|
263
|
+
onFallback == null ? void 0 : onFallback(methodName, args);
|
|
264
|
+
},
|
|
265
|
+
failHandler: throwOnError && new NativeMethodError(methodName)
|
|
266
|
+
}),
|
|
267
|
+
timeoutMs > 0 && timeout(timeoutMs, throwOnError)
|
|
268
|
+
].filter(Boolean)
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
willMethodThrowOnError(methodName) {
|
|
273
|
+
const { throwOnError } = this.options;
|
|
274
|
+
return throwOnError === true || Array.isArray(throwOnError) && throwOnError.includes(methodName);
|
|
275
|
+
}
|
|
276
|
+
createLoose(initialState) {
|
|
277
|
+
const { timeout: timeoutMs = this.defaultTimeoutMs, onFallback } = this.options;
|
|
278
|
+
return new Proxy(initialState, {
|
|
279
|
+
get: (target, methodName) => {
|
|
280
|
+
if (methodName in target && !["isWebViewBridgeAvailable", "isNativeMethodAvailable"].includes(
|
|
281
|
+
methodName
|
|
282
|
+
)) {
|
|
283
|
+
return target[methodName];
|
|
284
|
+
}
|
|
285
|
+
return this.createNativeMethod(
|
|
286
|
+
methodName,
|
|
287
|
+
this.willMethodThrowOnError(methodName),
|
|
288
|
+
timeoutMs,
|
|
289
|
+
onFallback
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
hydrate(bridgeMethods, nativeInitialState = {}) {
|
|
295
|
+
var _a;
|
|
296
|
+
const {
|
|
297
|
+
timeout: timeoutMs = this.defaultTimeoutMs,
|
|
298
|
+
onFallback,
|
|
299
|
+
onReady
|
|
300
|
+
} = this.options;
|
|
301
|
+
const initialState = bridgeMethods.reduce(
|
|
302
|
+
(acc, methodName) => {
|
|
303
|
+
return __spreadProps(__spreadValues({}, acc), {
|
|
304
|
+
[methodName]: this.createNativeMethod(
|
|
305
|
+
methodName,
|
|
306
|
+
this.willMethodThrowOnError(methodName),
|
|
307
|
+
timeoutMs,
|
|
308
|
+
onFallback
|
|
309
|
+
)
|
|
310
|
+
});
|
|
311
|
+
},
|
|
312
|
+
{}
|
|
313
|
+
);
|
|
314
|
+
const loose = this.createLoose(initialState);
|
|
315
|
+
const store = linkBridgeStore(
|
|
316
|
+
this.emitter,
|
|
317
|
+
initialState,
|
|
318
|
+
nativeInitialState
|
|
319
|
+
);
|
|
320
|
+
Object.assign(initialState, {
|
|
321
|
+
loose,
|
|
322
|
+
store,
|
|
323
|
+
isWebViewBridgeAvailable: Boolean(window.ReactNativeWebView) && bridgeMethods.length > 0,
|
|
324
|
+
isNativeMethodAvailable(methodName) {
|
|
325
|
+
return typeof methodName === "string" && Boolean(window.ReactNativeWebView) && bridgeMethods.includes(methodName);
|
|
326
|
+
},
|
|
327
|
+
addEventListener: (eventName, listener) => {
|
|
328
|
+
return this.emitter.on(`postMessage/${String(eventName)}`, listener);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
document.addEventListener("visibilitychange", () => {
|
|
332
|
+
if (document.visibilityState === "visible") {
|
|
333
|
+
this.postMessage("getBridgeState");
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
this.postMessage("getBridgeState");
|
|
337
|
+
const proxy = new Proxy(initialState, {
|
|
338
|
+
get: (target, methodName) => {
|
|
339
|
+
if (methodName in target) {
|
|
340
|
+
return target[methodName];
|
|
341
|
+
}
|
|
342
|
+
this.postMessage("fallback", {
|
|
343
|
+
method: methodName
|
|
344
|
+
});
|
|
345
|
+
if (this.willMethodThrowOnError(methodName)) {
|
|
346
|
+
return (...args) => {
|
|
347
|
+
onFallback == null ? void 0 : onFallback(methodName, args);
|
|
348
|
+
return Promise.reject(new MethodNotFoundError(methodName));
|
|
349
|
+
};
|
|
350
|
+
} else {
|
|
351
|
+
console.warn(
|
|
352
|
+
`[WebViewBridge] ${methodName} is not defined, using fallback.`
|
|
269
353
|
);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
]
|
|
278
|
-
|
|
354
|
+
}
|
|
355
|
+
return () => Promise.resolve();
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
for (const [eventName, ...args] of (_a = window.nativeBatchedEvents) != null ? _a : []) {
|
|
359
|
+
this.emitter.emit(eventName, ...args);
|
|
360
|
+
}
|
|
361
|
+
window.nativeBatchedEvents = [];
|
|
362
|
+
onReady == null ? void 0 : onReady(proxy);
|
|
363
|
+
this.$proxy = proxy;
|
|
364
|
+
return proxy;
|
|
365
|
+
}
|
|
366
|
+
get proxy() {
|
|
367
|
+
return this.$proxy;
|
|
368
|
+
}
|
|
279
369
|
};
|
|
370
|
+
|
|
371
|
+
// src/linkBridge.ts
|
|
280
372
|
var linkBridge = (options = {
|
|
281
373
|
timeout: 2e3,
|
|
282
374
|
throwOnError: false
|
|
283
375
|
}) => {
|
|
284
|
-
var _a
|
|
376
|
+
var _a;
|
|
285
377
|
if (typeof window === "undefined") {
|
|
286
378
|
return {
|
|
287
379
|
store: {
|
|
@@ -290,94 +382,23 @@ var linkBridge = (options = {
|
|
|
290
382
|
}
|
|
291
383
|
};
|
|
292
384
|
}
|
|
293
|
-
const {
|
|
294
|
-
timeout: timeoutMs = 2e3,
|
|
295
|
-
throwOnError = false,
|
|
296
|
-
onFallback,
|
|
297
|
-
onReady
|
|
298
|
-
} = options;
|
|
299
385
|
if (!window.ReactNativeWebView) {
|
|
300
386
|
console.warn("[WebViewBridge] Not in a WebView environment");
|
|
301
387
|
}
|
|
302
|
-
const
|
|
388
|
+
const emitter = createEvents();
|
|
303
389
|
if (!window.nativeEmitter) {
|
|
304
390
|
window.nativeEmitter = emitter;
|
|
305
391
|
}
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
methodName,
|
|
314
|
-
timeoutMs,
|
|
315
|
-
throwOnError: willMethodThrowOnError(methodName),
|
|
316
|
-
onFallback
|
|
317
|
-
})
|
|
318
|
-
});
|
|
319
|
-
},
|
|
320
|
-
{}
|
|
321
|
-
);
|
|
322
|
-
const loose = new Proxy(target, {
|
|
323
|
-
get: (target2, methodName) => {
|
|
324
|
-
if (methodName in target2 && !["isWebViewBridgeAvailable", "isNativeMethodAvailable"].includes(
|
|
325
|
-
methodName
|
|
326
|
-
)) {
|
|
327
|
-
return target2[methodName];
|
|
328
|
-
}
|
|
329
|
-
return createNativeMethod({
|
|
330
|
-
methodName,
|
|
331
|
-
timeoutMs,
|
|
332
|
-
throwOnError: willMethodThrowOnError(methodName),
|
|
333
|
-
onFallback
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
Object.assign(target, {
|
|
338
|
-
loose,
|
|
339
|
-
store: linkBridgeStore(target),
|
|
340
|
-
isWebViewBridgeAvailable: Boolean(window.ReactNativeWebView) && bridgeMethods.length > 0,
|
|
341
|
-
isNativeMethodAvailable(methodName) {
|
|
342
|
-
return typeof methodName === "string" && Boolean(window.ReactNativeWebView) && bridgeMethods.includes(methodName);
|
|
343
|
-
},
|
|
344
|
-
addEventListener: (eventName, listener) => {
|
|
345
|
-
return emitter.on(`postMessage/${String(eventName)}`, listener);
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
const proxy = new Proxy(target, {
|
|
349
|
-
get: (target2, methodName) => {
|
|
350
|
-
var _a2;
|
|
351
|
-
if (methodName in target2) {
|
|
352
|
-
return target2[methodName];
|
|
353
|
-
}
|
|
354
|
-
(_a2 = window.ReactNativeWebView) == null ? void 0 : _a2.postMessage(
|
|
355
|
-
JSON.stringify({
|
|
356
|
-
type: "fallback",
|
|
357
|
-
body: {
|
|
358
|
-
method: methodName
|
|
359
|
-
}
|
|
360
|
-
})
|
|
361
|
-
);
|
|
362
|
-
if (willMethodThrowOnError(methodName)) {
|
|
363
|
-
return (...args) => {
|
|
364
|
-
onFallback == null ? void 0 : onFallback(methodName, args);
|
|
365
|
-
Promise.reject(new MethodNotFoundError(methodName));
|
|
366
|
-
};
|
|
367
|
-
} else {
|
|
368
|
-
console.warn(
|
|
369
|
-
`[WebViewBridge] ${methodName} is not defined, using fallback.`
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
|
-
return () => Promise.resolve();
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
for (const [eventName, ...args] of (_b = window.nativeBatchedEvents) != null ? _b : []) {
|
|
376
|
-
emitter.emit(eventName, ...args);
|
|
392
|
+
const bridgeMethods = (_a = window.__bridgeMethods__) != null ? _a : [];
|
|
393
|
+
const instance = new BridgeInstance(emitter, bridgeMethods, options);
|
|
394
|
+
if (bridgeMethods.length === 0) {
|
|
395
|
+
const unsubscribe = emitter.on("hydrate", ({ bridgeMethods: bridgeMethods2 }) => {
|
|
396
|
+
instance.hydrate(bridgeMethods2);
|
|
397
|
+
unsubscribe();
|
|
398
|
+
});
|
|
377
399
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
return proxy;
|
|
400
|
+
instance.hydrate(bridgeMethods);
|
|
401
|
+
return instance.proxy;
|
|
381
402
|
};
|
|
382
403
|
|
|
383
404
|
// src/linkNativeMethod.ts
|
|
@@ -396,8 +417,8 @@ var registerWebMethod = (bridge) => {
|
|
|
396
417
|
}
|
|
397
418
|
const bridgeEntries = Object.entries(bridge);
|
|
398
419
|
const bridgeNames = Object.keys(bridge);
|
|
399
|
-
const
|
|
400
|
-
window.webEmitter =
|
|
420
|
+
const emitter = createEvents();
|
|
421
|
+
window.webEmitter = emitter;
|
|
401
422
|
for (const [funcName, func] of bridgeEntries) {
|
|
402
423
|
const $func = (eventId, args) => __async(void 0, null, function* () {
|
|
403
424
|
var _a, _b;
|
|
@@ -418,7 +439,7 @@ var registerWebMethod = (bridge) => {
|
|
|
418
439
|
);
|
|
419
440
|
}
|
|
420
441
|
});
|
|
421
|
-
|
|
442
|
+
emitter.on(funcName, $func);
|
|
422
443
|
}
|
|
423
444
|
const register = () => {
|
|
424
445
|
var _a;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Bridge, BridgeStore, ExcludePrimitive, ExtractStore, ParserSchema } from "../../../../shared/util/src/types";
|
|
2
|
+
import { DefaultEmitter } from "../../../../shared/util/src";
|
|
3
|
+
import { LinkBridgeOptions } from "../linkBridge";
|
|
4
|
+
import { LinkBridge } from "../types";
|
|
5
|
+
export declare class BridgeInstance<T extends BridgeStore<T extends Bridge ? T : any>, V extends ParserSchema<any> = ParserSchema<any>> {
|
|
6
|
+
emitter: DefaultEmitter;
|
|
7
|
+
bridgeMethods: string[];
|
|
8
|
+
private options;
|
|
9
|
+
private defaultTimeoutMs;
|
|
10
|
+
private $proxy;
|
|
11
|
+
constructor(emitter: DefaultEmitter, bridgeMethods: string[], options: LinkBridgeOptions<T, V>);
|
|
12
|
+
private postMessage;
|
|
13
|
+
private createNativeMethod;
|
|
14
|
+
private willMethodThrowOnError;
|
|
15
|
+
private createLoose;
|
|
16
|
+
hydrate(bridgeMethods: string[], nativeInitialState?: Partial<T>): LinkBridge<ExtractStore<T>, Omit<T, "setState">, V>;
|
|
17
|
+
get proxy(): LinkBridge<ExcludePrimitive<ExtractStore<T>>, Omit<T, "setState">, V>;
|
|
18
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Bridge, BridgeStore, OnlyJSON } from "../../../../shared/util/src/types";
|
|
2
|
+
import { DefaultEmitter } from "../../../../shared/util/src";
|
|
2
3
|
export type Store<BridgeObject extends Bridge> = ({ get, set, }: {
|
|
3
4
|
get: () => BridgeObject;
|
|
4
5
|
set: (newState: Partial<OnlyJSON<BridgeObject>>) => void;
|
|
5
6
|
}) => BridgeObject;
|
|
6
|
-
export declare const linkBridgeStore: <T extends BridgeStore<T extends Bridge ? T : any>>(initialState?: Partial<T>) => Omit<T, "setState">;
|
|
7
|
+
export declare const linkBridgeStore: <T extends BridgeStore<T extends Bridge ? T : any>>(emitter: DefaultEmitter, initialState?: Partial<T>, nativeInitialState?: Partial<T>) => Omit<T, "setState">;
|
|
@@ -11,9 +11,10 @@ export interface EventEmitter<Events extends EventsMap = DefaultEvents> {
|
|
|
11
11
|
}>;
|
|
12
12
|
on<K extends keyof Events>(this: this, event: K, cb: Events[K]): () => void;
|
|
13
13
|
}
|
|
14
|
+
export type DefaultEmitter = EventEmitter<DefaultEvents>;
|
|
14
15
|
export declare const createEvents: <Events extends EventsMap = DefaultEvents>() => EventEmitter<Events>;
|
|
15
16
|
export interface CreateResolverOptions {
|
|
16
|
-
emitter:
|
|
17
|
+
emitter: DefaultEmitter;
|
|
17
18
|
evaluate: () => void;
|
|
18
19
|
eventId: string;
|
|
19
20
|
failHandler?: Error | false;
|