@webview-bridge/web 1.0.5 → 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.
- package/dist/commonjs/index.cjs +83 -31
- package/dist/module/index.mjs +82 -31
- package/dist/typescript/packages/web/src/error.d.ts +3 -0
- package/dist/typescript/packages/web/src/linkNativeMethod.d.ts +4 -4
- package/dist/typescript/packages/web/src/types/index.d.ts +8 -2
- package/dist/typescript/shared/util/src/createEvents.d.ts +1 -1
- package/dist/typescript/shared/util/src/timeout.d.ts +1 -1
- package/package.json +1 -1
package/dist/commonjs/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
MethodNotFoundError: () => MethodNotFoundError,
|
|
24
|
+
NativeMethodError: () => NativeMethodError,
|
|
24
25
|
linkNativeMethod: () => linkNativeMethod,
|
|
25
26
|
registerWebMethod: () => registerWebMethod
|
|
26
27
|
});
|
|
@@ -33,6 +34,12 @@ var MethodNotFoundError = class extends Error {
|
|
|
33
34
|
this.name = "MethodNotFoundError";
|
|
34
35
|
}
|
|
35
36
|
};
|
|
37
|
+
var NativeMethodError = class extends Error {
|
|
38
|
+
constructor(methodName) {
|
|
39
|
+
super(`An error occurred in the native bridge: ${methodName}`);
|
|
40
|
+
this.name = "NativeMethodError";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
36
43
|
|
|
37
44
|
// ../../shared/util/src/createEvents.ts
|
|
38
45
|
var createEvents = () => ({
|
|
@@ -50,12 +57,23 @@ var createEvents = () => ({
|
|
|
50
57
|
};
|
|
51
58
|
}
|
|
52
59
|
});
|
|
53
|
-
var createResolver = (emitter2, method, eventId, evaluate) => {
|
|
54
|
-
return new Promise((resolve) => {
|
|
55
|
-
const unbind = emitter2.on(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
var createResolver = (emitter2, method, eventId, evaluate, failHandler = false) => {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const unbind = emitter2.on(
|
|
63
|
+
`${method}-${eventId}`,
|
|
64
|
+
(data, throwOccurred) => {
|
|
65
|
+
unbind();
|
|
66
|
+
if (throwOccurred) {
|
|
67
|
+
if (failHandler instanceof Error) {
|
|
68
|
+
reject(failHandler);
|
|
69
|
+
} else {
|
|
70
|
+
resolve(void 0);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
resolve(data);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
);
|
|
59
77
|
evaluate();
|
|
60
78
|
});
|
|
61
79
|
};
|
|
@@ -72,16 +90,44 @@ var createRandomId = (size = ID_LENGTH) => {
|
|
|
72
90
|
};
|
|
73
91
|
|
|
74
92
|
// ../../shared/util/src/timeout.ts
|
|
75
|
-
var timeout = (ms) => {
|
|
76
|
-
return new Promise((
|
|
93
|
+
var timeout = (ms, throwOnError = true) => {
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
77
95
|
setTimeout(() => {
|
|
78
|
-
|
|
96
|
+
if (throwOnError) {
|
|
97
|
+
reject(new Error("Timeout"));
|
|
98
|
+
} else {
|
|
99
|
+
resolve(void 0);
|
|
100
|
+
}
|
|
79
101
|
}, ms);
|
|
80
102
|
});
|
|
81
103
|
};
|
|
82
104
|
|
|
83
105
|
// src/linkNativeMethod.ts
|
|
84
106
|
var emitter = createEvents();
|
|
107
|
+
var createNativeMethod = (method, timeoutMs, throwOnError) => (...args) => {
|
|
108
|
+
const eventId = createRandomId();
|
|
109
|
+
return Promise.race([
|
|
110
|
+
createResolver(
|
|
111
|
+
emitter,
|
|
112
|
+
method,
|
|
113
|
+
eventId,
|
|
114
|
+
() => {
|
|
115
|
+
window.ReactNativeWebView?.postMessage(
|
|
116
|
+
JSON.stringify({
|
|
117
|
+
type: "bridge",
|
|
118
|
+
body: {
|
|
119
|
+
method,
|
|
120
|
+
eventId,
|
|
121
|
+
args
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
);
|
|
125
|
+
},
|
|
126
|
+
throwOnError && new NativeMethodError(method)
|
|
127
|
+
),
|
|
128
|
+
timeout(timeoutMs, throwOnError)
|
|
129
|
+
]);
|
|
130
|
+
};
|
|
85
131
|
var linkNativeMethod = (options = {
|
|
86
132
|
timeout: 2e3,
|
|
87
133
|
throwOnError: false
|
|
@@ -98,35 +144,42 @@ var linkNativeMethod = (options = {
|
|
|
98
144
|
if (!window.nativeEmitter) {
|
|
99
145
|
window.nativeEmitter = emitter;
|
|
100
146
|
}
|
|
147
|
+
const willMethodThrowOnError = (methodName) => {
|
|
148
|
+
return throwOnError === true || Array.isArray(throwOnError) && throwOnError.includes(methodName);
|
|
149
|
+
};
|
|
101
150
|
const target = bridgeMethods.reduce(
|
|
102
151
|
(acc, method) => {
|
|
103
152
|
return {
|
|
104
153
|
...acc,
|
|
105
|
-
[method]: (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
JSON.stringify({
|
|
111
|
-
type: "bridge",
|
|
112
|
-
body: {
|
|
113
|
-
method,
|
|
114
|
-
eventId,
|
|
115
|
-
args
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
);
|
|
119
|
-
}),
|
|
120
|
-
timeout(timeoutMs)
|
|
121
|
-
]);
|
|
122
|
-
}
|
|
154
|
+
[method]: createNativeMethod(
|
|
155
|
+
method,
|
|
156
|
+
timeoutMs,
|
|
157
|
+
willMethodThrowOnError(method)
|
|
158
|
+
)
|
|
123
159
|
};
|
|
124
160
|
},
|
|
125
161
|
{
|
|
126
162
|
isWebViewBridgeAvailable: Boolean(window.ReactNativeWebView) && bridgeMethods.length > 0,
|
|
127
|
-
isNativeMethodAvailable
|
|
163
|
+
isNativeMethodAvailable(method) {
|
|
164
|
+
return typeof method === "string" && Boolean(window.ReactNativeWebView) && bridgeMethods.includes(method);
|
|
165
|
+
}
|
|
128
166
|
}
|
|
129
167
|
);
|
|
168
|
+
const loose = new Proxy(target, {
|
|
169
|
+
get: (target2, method) => {
|
|
170
|
+
if (method in target2 && !["isWebViewBridgeAvailable", "isNativeMethodAvailable"].includes(
|
|
171
|
+
method
|
|
172
|
+
)) {
|
|
173
|
+
return target2[method];
|
|
174
|
+
}
|
|
175
|
+
return createNativeMethod(
|
|
176
|
+
method,
|
|
177
|
+
timeoutMs,
|
|
178
|
+
willMethodThrowOnError(method)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
Object.assign(target, { loose });
|
|
130
183
|
return new Proxy(target, {
|
|
131
184
|
get: (target2, method) => {
|
|
132
185
|
if (method in target2) {
|
|
@@ -141,9 +194,7 @@ var linkNativeMethod = (options = {
|
|
|
141
194
|
})
|
|
142
195
|
);
|
|
143
196
|
onFallback?.(method);
|
|
144
|
-
if (
|
|
145
|
-
return () => Promise.reject(new MethodNotFoundError(method));
|
|
146
|
-
} else if (Array.isArray(throwOnError) && throwOnError.includes(method)) {
|
|
197
|
+
if (willMethodThrowOnError(method)) {
|
|
147
198
|
return () => Promise.reject(new MethodNotFoundError(method));
|
|
148
199
|
} else {
|
|
149
200
|
console.warn(
|
|
@@ -196,6 +247,7 @@ var registerWebMethod = (bridge) => {
|
|
|
196
247
|
// Annotate the CommonJS export names for ESM import in node:
|
|
197
248
|
0 && (module.exports = {
|
|
198
249
|
MethodNotFoundError,
|
|
250
|
+
NativeMethodError,
|
|
199
251
|
linkNativeMethod,
|
|
200
252
|
registerWebMethod
|
|
201
253
|
});
|
package/dist/module/index.mjs
CHANGED
|
@@ -5,6 +5,12 @@ var MethodNotFoundError = class extends Error {
|
|
|
5
5
|
this.name = "MethodNotFoundError";
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
|
+
var NativeMethodError = class extends Error {
|
|
9
|
+
constructor(methodName) {
|
|
10
|
+
super(`An error occurred in the native bridge: ${methodName}`);
|
|
11
|
+
this.name = "NativeMethodError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
8
14
|
|
|
9
15
|
// ../../shared/util/src/createEvents.ts
|
|
10
16
|
var createEvents = () => ({
|
|
@@ -22,12 +28,23 @@ var createEvents = () => ({
|
|
|
22
28
|
};
|
|
23
29
|
}
|
|
24
30
|
});
|
|
25
|
-
var createResolver = (emitter2, method, eventId, evaluate) => {
|
|
26
|
-
return new Promise((resolve) => {
|
|
27
|
-
const unbind = emitter2.on(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
var createResolver = (emitter2, method, eventId, evaluate, failHandler = false) => {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const unbind = emitter2.on(
|
|
34
|
+
`${method}-${eventId}`,
|
|
35
|
+
(data, throwOccurred) => {
|
|
36
|
+
unbind();
|
|
37
|
+
if (throwOccurred) {
|
|
38
|
+
if (failHandler instanceof Error) {
|
|
39
|
+
reject(failHandler);
|
|
40
|
+
} else {
|
|
41
|
+
resolve(void 0);
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
resolve(data);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
);
|
|
31
48
|
evaluate();
|
|
32
49
|
});
|
|
33
50
|
};
|
|
@@ -44,16 +61,44 @@ var createRandomId = (size = ID_LENGTH) => {
|
|
|
44
61
|
};
|
|
45
62
|
|
|
46
63
|
// ../../shared/util/src/timeout.ts
|
|
47
|
-
var timeout = (ms) => {
|
|
48
|
-
return new Promise((
|
|
64
|
+
var timeout = (ms, throwOnError = true) => {
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
49
66
|
setTimeout(() => {
|
|
50
|
-
|
|
67
|
+
if (throwOnError) {
|
|
68
|
+
reject(new Error("Timeout"));
|
|
69
|
+
} else {
|
|
70
|
+
resolve(void 0);
|
|
71
|
+
}
|
|
51
72
|
}, ms);
|
|
52
73
|
});
|
|
53
74
|
};
|
|
54
75
|
|
|
55
76
|
// src/linkNativeMethod.ts
|
|
56
77
|
var emitter = createEvents();
|
|
78
|
+
var createNativeMethod = (method, timeoutMs, throwOnError) => (...args) => {
|
|
79
|
+
const eventId = createRandomId();
|
|
80
|
+
return Promise.race([
|
|
81
|
+
createResolver(
|
|
82
|
+
emitter,
|
|
83
|
+
method,
|
|
84
|
+
eventId,
|
|
85
|
+
() => {
|
|
86
|
+
window.ReactNativeWebView?.postMessage(
|
|
87
|
+
JSON.stringify({
|
|
88
|
+
type: "bridge",
|
|
89
|
+
body: {
|
|
90
|
+
method,
|
|
91
|
+
eventId,
|
|
92
|
+
args
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
throwOnError && new NativeMethodError(method)
|
|
98
|
+
),
|
|
99
|
+
timeout(timeoutMs, throwOnError)
|
|
100
|
+
]);
|
|
101
|
+
};
|
|
57
102
|
var linkNativeMethod = (options = {
|
|
58
103
|
timeout: 2e3,
|
|
59
104
|
throwOnError: false
|
|
@@ -70,35 +115,42 @@ var linkNativeMethod = (options = {
|
|
|
70
115
|
if (!window.nativeEmitter) {
|
|
71
116
|
window.nativeEmitter = emitter;
|
|
72
117
|
}
|
|
118
|
+
const willMethodThrowOnError = (methodName) => {
|
|
119
|
+
return throwOnError === true || Array.isArray(throwOnError) && throwOnError.includes(methodName);
|
|
120
|
+
};
|
|
73
121
|
const target = bridgeMethods.reduce(
|
|
74
122
|
(acc, method) => {
|
|
75
123
|
return {
|
|
76
124
|
...acc,
|
|
77
|
-
[method]: (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
JSON.stringify({
|
|
83
|
-
type: "bridge",
|
|
84
|
-
body: {
|
|
85
|
-
method,
|
|
86
|
-
eventId,
|
|
87
|
-
args
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
);
|
|
91
|
-
}),
|
|
92
|
-
timeout(timeoutMs)
|
|
93
|
-
]);
|
|
94
|
-
}
|
|
125
|
+
[method]: createNativeMethod(
|
|
126
|
+
method,
|
|
127
|
+
timeoutMs,
|
|
128
|
+
willMethodThrowOnError(method)
|
|
129
|
+
)
|
|
95
130
|
};
|
|
96
131
|
},
|
|
97
132
|
{
|
|
98
133
|
isWebViewBridgeAvailable: Boolean(window.ReactNativeWebView) && bridgeMethods.length > 0,
|
|
99
|
-
isNativeMethodAvailable
|
|
134
|
+
isNativeMethodAvailable(method) {
|
|
135
|
+
return typeof method === "string" && Boolean(window.ReactNativeWebView) && bridgeMethods.includes(method);
|
|
136
|
+
}
|
|
100
137
|
}
|
|
101
138
|
);
|
|
139
|
+
const loose = new Proxy(target, {
|
|
140
|
+
get: (target2, method) => {
|
|
141
|
+
if (method in target2 && !["isWebViewBridgeAvailable", "isNativeMethodAvailable"].includes(
|
|
142
|
+
method
|
|
143
|
+
)) {
|
|
144
|
+
return target2[method];
|
|
145
|
+
}
|
|
146
|
+
return createNativeMethod(
|
|
147
|
+
method,
|
|
148
|
+
timeoutMs,
|
|
149
|
+
willMethodThrowOnError(method)
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
Object.assign(target, { loose });
|
|
102
154
|
return new Proxy(target, {
|
|
103
155
|
get: (target2, method) => {
|
|
104
156
|
if (method in target2) {
|
|
@@ -113,9 +165,7 @@ var linkNativeMethod = (options = {
|
|
|
113
165
|
})
|
|
114
166
|
);
|
|
115
167
|
onFallback?.(method);
|
|
116
|
-
if (
|
|
117
|
-
return () => Promise.reject(new MethodNotFoundError(method));
|
|
118
|
-
} else if (Array.isArray(throwOnError) && throwOnError.includes(method)) {
|
|
168
|
+
if (willMethodThrowOnError(method)) {
|
|
119
169
|
return () => Promise.reject(new MethodNotFoundError(method));
|
|
120
170
|
} else {
|
|
121
171
|
console.warn(
|
|
@@ -167,6 +217,7 @@ var registerWebMethod = (bridge) => {
|
|
|
167
217
|
};
|
|
168
218
|
export {
|
|
169
219
|
MethodNotFoundError,
|
|
220
|
+
NativeMethodError,
|
|
170
221
|
linkNativeMethod,
|
|
171
222
|
registerWebMethod
|
|
172
223
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Bridge,
|
|
1
|
+
import { Bridge, NativeMethod } from "./types";
|
|
2
2
|
export interface LinkNativeMethodOptions<BridgeObject extends Bridge> {
|
|
3
3
|
timeout?: number;
|
|
4
|
-
throwOnError?: boolean | (keyof BridgeObject)[];
|
|
5
|
-
onFallback?: (method:
|
|
4
|
+
throwOnError?: boolean | (keyof BridgeObject)[] | string[];
|
|
5
|
+
onFallback?: (method: string) => void;
|
|
6
6
|
}
|
|
7
|
-
export declare const linkNativeMethod: <BridgeObject extends Bridge>(options?: LinkNativeMethodOptions<BridgeObject>) =>
|
|
7
|
+
export declare const linkNativeMethod: <BridgeObject extends Bridge>(options?: LinkNativeMethodOptions<BridgeObject>) => NativeMethod<BridgeObject>;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export type AsyncFunction = (...args: any[]) => Promise<any>;
|
|
2
2
|
export type Bridge = Record<string, AsyncFunction>;
|
|
3
|
-
export type
|
|
3
|
+
export type NativeMethod<T> = {
|
|
4
4
|
isWebViewBridgeAvailable: boolean;
|
|
5
|
-
isNativeMethodAvailable
|
|
5
|
+
isNativeMethodAvailable(method: keyof T): boolean;
|
|
6
|
+
isNativeMethodAvailable(method: string): boolean;
|
|
7
|
+
loose: {
|
|
8
|
+
[K in keyof T]: (...args: any[]) => any;
|
|
9
|
+
} & {
|
|
10
|
+
[key: string]: (...args: any[]) => any;
|
|
11
|
+
};
|
|
6
12
|
} & T;
|
|
@@ -12,5 +12,5 @@ export interface EventEmitter<Events extends EventsMap = DefaultEvents> {
|
|
|
12
12
|
on<K extends keyof Events>(this: this, event: K, cb: Events[K]): () => void;
|
|
13
13
|
}
|
|
14
14
|
export declare const createEvents: <Events extends EventsMap = DefaultEvents>() => EventEmitter<Events>;
|
|
15
|
-
export declare const createResolver: (emitter: EventEmitter<DefaultEvents>, method: string, eventId: string, evaluate: () => void) => Promise<unknown>;
|
|
15
|
+
export declare const createResolver: (emitter: EventEmitter<DefaultEvents>, method: string, eventId: string, evaluate: () => void, failHandler?: Error | false) => Promise<unknown>;
|
|
16
16
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const timeout: (ms: number) => Promise<unknown>;
|
|
1
|
+
export declare const timeout: (ms: number, throwOnError?: boolean) => Promise<unknown>;
|