@wvb/bridge 0.1.0-next.3603a22
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/CHANGELOG.md +8 -0
- package/README.md +1 -0
- package/dist/index-eeBgJJSy.d.cts +198 -0
- package/dist/index-eeBgJJSy.d.ts +198 -0
- package/dist/index.cjs +340 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +331 -0
- package/dist/platform-mock-Bvaw9qjP.js +50 -0
- package/dist/platform-mock-DrAsRJ91.cjs +73 -0
- package/dist/testing/index.cjs +117 -0
- package/dist/testing/index.d.cts +75 -0
- package/dist/testing/index.d.ts +75 -0
- package/dist/testing/index.js +113 -0
- package/package.json +53 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_platform_mock = require("./platform-mock-DrAsRJ91.cjs");
|
|
3
|
+
let _tauri_apps_api_core = require("@tauri-apps/api/core");
|
|
4
|
+
//#region src/error.ts
|
|
5
|
+
const BridgeErrorCode = {
|
|
6
|
+
/** `params` was missing or had the wrong shape/type. */
|
|
7
|
+
InvalidParams: "invalid_params",
|
|
8
|
+
/** A `remote.*` command was invoked but no remote is configured. */
|
|
9
|
+
RemoteNotInitialized: "remote_not_initialized",
|
|
10
|
+
/** An `updater.*` command was invoked but no updater is configured. */
|
|
11
|
+
UpdaterNotInitialized: "updater_not_initialized",
|
|
12
|
+
/** No handler is registered for the requested command name. */
|
|
13
|
+
HandlerNotFound: "handler_not_found",
|
|
14
|
+
/** The handler returned a value that is not JSON-encodable. */
|
|
15
|
+
UnencodableResult: "unencodable_result"
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Error thrown by `@wvb/bridge` when an `invoke()` command rejects, regardless of
|
|
19
|
+
* platform.
|
|
20
|
+
*/
|
|
21
|
+
var BridgeError = class BridgeError extends Error {
|
|
22
|
+
static of(code, message = "") {
|
|
23
|
+
return new BridgeError({
|
|
24
|
+
code,
|
|
25
|
+
message
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
static from(value) {
|
|
29
|
+
if (value instanceof BridgeError) return value;
|
|
30
|
+
if (isBridgeErrorData(value)) return new BridgeError(value);
|
|
31
|
+
if (value instanceof Error) return new BridgeError({ message: value.message });
|
|
32
|
+
if (typeof value === "string") return new BridgeError({ message: value });
|
|
33
|
+
return new BridgeError({ message: "unknown bridge error" });
|
|
34
|
+
}
|
|
35
|
+
constructor(data) {
|
|
36
|
+
super(data.message);
|
|
37
|
+
require_platform_mock._defineProperty(this, "name", "BridgeError");
|
|
38
|
+
require_platform_mock._defineProperty(this, "code", void 0);
|
|
39
|
+
this.code = data.code;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
function isBridgeError(e) {
|
|
43
|
+
return e != null && typeof e === "object" && "name" in e && e.name === "BridgeError";
|
|
44
|
+
}
|
|
45
|
+
function isBridgeErrorData(value) {
|
|
46
|
+
if (typeof value !== "object" || value === null) return false;
|
|
47
|
+
const data = value;
|
|
48
|
+
return typeof data.message === "string" && (data.code === void 0 || typeof data.code === "string");
|
|
49
|
+
}
|
|
50
|
+
function unknownPlatform() {
|
|
51
|
+
throw new Error("Unknown platform. Make sure native webview supports webview-bundle.");
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/callback.ts
|
|
55
|
+
var CallbackBag = class {
|
|
56
|
+
constructor() {
|
|
57
|
+
require_platform_mock._defineProperty(this, "ids", []);
|
|
58
|
+
}
|
|
59
|
+
generate(callback) {
|
|
60
|
+
const w = require_platform_mock.getWindow();
|
|
61
|
+
w.__wvb_bridge_callbacks__ ?? (w.__wvb_bridge_callbacks__ = {});
|
|
62
|
+
const id = `cb_${generateId()}`;
|
|
63
|
+
w.__wvb_bridge_callbacks__[id] = callback;
|
|
64
|
+
this.ids.push(id);
|
|
65
|
+
return `(
|
|
66
|
+
function() {
|
|
67
|
+
var cb = __wvb_bridge_callbacks__ != null
|
|
68
|
+
? __wvb_bridge_callbacks__["${id}"]
|
|
69
|
+
: undefined;
|
|
70
|
+
if (cb == null) {
|
|
71
|
+
throw new Error("cannot find callback: ${id}");
|
|
72
|
+
}
|
|
73
|
+
return cb.apply(undefined, arguments);
|
|
74
|
+
}
|
|
75
|
+
)`.replace(/(\n|\s{2,})/g, " ");
|
|
76
|
+
}
|
|
77
|
+
clean() {
|
|
78
|
+
const w = require_platform_mock.getWindow();
|
|
79
|
+
for (const id of this.ids) if (w.__wvb_bridge_callbacks__ != null) Reflect.deleteProperty(w.__wvb_bridge_callbacks__, id);
|
|
80
|
+
this.ids = [];
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
function generateId() {
|
|
84
|
+
const w = require_platform_mock.getWindow();
|
|
85
|
+
if (typeof w?.crypto?.randomUUID === "function") return w.crypto.randomUUID().replace(/-/g, "");
|
|
86
|
+
const bytes = new Uint8Array(16);
|
|
87
|
+
if (typeof w?.crypto?.getRandomValues === "function") w.crypto.getRandomValues(bytes);
|
|
88
|
+
else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
89
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
90
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
91
|
+
let id = "";
|
|
92
|
+
for (const byte of bytes) id += byte.toString(16).padStart(2, "0");
|
|
93
|
+
return id;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/platform.ts
|
|
97
|
+
function isElectron() {
|
|
98
|
+
return require_platform_mock.getWindow()?.wvbElectron != null;
|
|
99
|
+
}
|
|
100
|
+
function isAndroid() {
|
|
101
|
+
return require_platform_mock.getWindow()?.wvbAndroid != null;
|
|
102
|
+
}
|
|
103
|
+
function isIos() {
|
|
104
|
+
return require_platform_mock.getWindow()?.webkit?.messageHandlers?.wvbIos != null;
|
|
105
|
+
}
|
|
106
|
+
function resolveType() {
|
|
107
|
+
const mocked = require_platform_mock.getWindow()[require_platform_mock.PLATFORM_MOCK_KEY];
|
|
108
|
+
if (mocked != null) return mocked;
|
|
109
|
+
if (isElectron()) return "electron";
|
|
110
|
+
if ((0, _tauri_apps_api_core.isTauri)()) return "tauri";
|
|
111
|
+
if (isAndroid()) return "android";
|
|
112
|
+
if (isIos()) return "ios";
|
|
113
|
+
}
|
|
114
|
+
const platform = {
|
|
115
|
+
get type() {
|
|
116
|
+
return resolveType();
|
|
117
|
+
},
|
|
118
|
+
get isElectron() {
|
|
119
|
+
return resolveType() === "electron";
|
|
120
|
+
},
|
|
121
|
+
get isTauri() {
|
|
122
|
+
return resolveType() === "tauri";
|
|
123
|
+
},
|
|
124
|
+
get isAndroid() {
|
|
125
|
+
return resolveType() === "android";
|
|
126
|
+
},
|
|
127
|
+
get isIos() {
|
|
128
|
+
return resolveType() === "ios";
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/utils.ts
|
|
133
|
+
function snakeCase(str) {
|
|
134
|
+
return str.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").trim().replace(/ /g, "_").toLowerCase();
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
//#region src/invoke.ts
|
|
138
|
+
/**
|
|
139
|
+
* Invokes a native bridge command and resolves its result.
|
|
140
|
+
* Before using the bridge, make sure native supports webview-bundle.
|
|
141
|
+
*
|
|
142
|
+
* Throws a {@link BridgeError} on failure.
|
|
143
|
+
*/
|
|
144
|
+
async function invoke(name, params) {
|
|
145
|
+
try {
|
|
146
|
+
return await invokeInner(name, params);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
throw BridgeError.from(error);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function invokeInner(name, params) {
|
|
152
|
+
const mock = require_platform_mock.getWindow()[require_platform_mock.INVOKE_MOCK_KEY];
|
|
153
|
+
if (mock != null) return mock(name, params);
|
|
154
|
+
switch (platform.type) {
|
|
155
|
+
case "electron": return require_platform_mock.getWindow().wvbElectron.invoke(name, params);
|
|
156
|
+
case "tauri": return (0, _tauri_apps_api_core.invoke)(toTauriCommand(name), params);
|
|
157
|
+
case "android":
|
|
158
|
+
case "ios": {
|
|
159
|
+
const bridge = getMobileBridge(platform.type);
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
const bag = new CallbackBag();
|
|
162
|
+
const success = bag.generate((result) => {
|
|
163
|
+
resolve(result);
|
|
164
|
+
bag.clean();
|
|
165
|
+
});
|
|
166
|
+
const error = bag.generate((error) => {
|
|
167
|
+
reject(error);
|
|
168
|
+
bag.clean();
|
|
169
|
+
});
|
|
170
|
+
try {
|
|
171
|
+
bridge.postMessage(name, params, success, error);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
bag.clean();
|
|
174
|
+
reject(error);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
default: unknownPlatform();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function getMobileBridge(platform) {
|
|
182
|
+
switch (platform) {
|
|
183
|
+
case "android": {
|
|
184
|
+
const w = require_platform_mock.getWindow();
|
|
185
|
+
return { postMessage: (name, params, success, error) => w.wvbAndroid.postMessage(JSON.stringify({
|
|
186
|
+
name,
|
|
187
|
+
params,
|
|
188
|
+
success,
|
|
189
|
+
error
|
|
190
|
+
})) };
|
|
191
|
+
}
|
|
192
|
+
case "ios": {
|
|
193
|
+
const w = require_platform_mock.getWindow();
|
|
194
|
+
return { postMessage: (name, params, success, error) => w.webkit.messageHandlers.wvbIos.postMessage({
|
|
195
|
+
name,
|
|
196
|
+
params,
|
|
197
|
+
success,
|
|
198
|
+
error
|
|
199
|
+
}) };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function toTauriCommand(name) {
|
|
204
|
+
return `plugin:wvb-tauri|${snakeCase(name)}`;
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/remote.ts
|
|
208
|
+
async function listBundles$1(channel) {
|
|
209
|
+
return invoke("remoteListBundles", { channel });
|
|
210
|
+
}
|
|
211
|
+
async function getInfo(bundleName, channel) {
|
|
212
|
+
return invoke("remoteGetInfo", {
|
|
213
|
+
bundleName,
|
|
214
|
+
channel
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
async function download$1(bundleName, channel) {
|
|
218
|
+
return invoke("remoteDownload", {
|
|
219
|
+
bundleName,
|
|
220
|
+
channel
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
async function downloadVersion(bundleName, version) {
|
|
224
|
+
return invoke("remoteDownloadVersion", {
|
|
225
|
+
bundleName,
|
|
226
|
+
version
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
const remote = {
|
|
230
|
+
listBundles: listBundles$1,
|
|
231
|
+
getInfo,
|
|
232
|
+
download: download$1,
|
|
233
|
+
downloadVersion
|
|
234
|
+
};
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region src/source.ts
|
|
237
|
+
async function listBundles() {
|
|
238
|
+
return invoke("sourceListBundles");
|
|
239
|
+
}
|
|
240
|
+
async function loadVersion(bundleName) {
|
|
241
|
+
return invoke("sourceLoadVersion", { bundleName });
|
|
242
|
+
}
|
|
243
|
+
async function updateVersion(bundleName, version) {
|
|
244
|
+
return invoke("sourceUpdateVersion", {
|
|
245
|
+
bundleName,
|
|
246
|
+
version
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
async function resolveFilepath(bundleName) {
|
|
250
|
+
return invoke("sourceResolveFilepath", { bundleName });
|
|
251
|
+
}
|
|
252
|
+
async function getBuiltinBundleFilepath(bundleName, version) {
|
|
253
|
+
return invoke("sourceGetBuiltinBundleFilepath", {
|
|
254
|
+
bundleName,
|
|
255
|
+
version
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
async function getRemoteBundleFilepath(bundleName, version) {
|
|
259
|
+
return invoke("sourceGetRemoteBundleFilepath", {
|
|
260
|
+
bundleName,
|
|
261
|
+
version
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
async function loadBuiltinMetadata(bundleName, version) {
|
|
265
|
+
return invoke("sourceLoadBuiltinMetadata", {
|
|
266
|
+
bundleName,
|
|
267
|
+
version
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
async function loadRemoteMetadata(bundleName, version) {
|
|
271
|
+
return invoke("sourceLoadRemoteMetadata", {
|
|
272
|
+
bundleName,
|
|
273
|
+
version
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
async function unloadDescriptor(bundleName) {
|
|
277
|
+
return invoke("sourceUnloadDescriptor", { bundleName });
|
|
278
|
+
}
|
|
279
|
+
async function removeRemoteBundle(bundleName, version) {
|
|
280
|
+
return invoke("sourceRemoveRemoteBundle", {
|
|
281
|
+
bundleName,
|
|
282
|
+
version
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
async function remoteRetainedVersions(bundleName) {
|
|
286
|
+
return invoke("sourceRemoteRetainedVersions", { bundleName });
|
|
287
|
+
}
|
|
288
|
+
async function pruneRemoteBundles(bundleName) {
|
|
289
|
+
return invoke("sourcePruneRemoteBundles", { bundleName });
|
|
290
|
+
}
|
|
291
|
+
const source = {
|
|
292
|
+
listBundles,
|
|
293
|
+
loadVersion,
|
|
294
|
+
updateVersion,
|
|
295
|
+
resolveFilepath,
|
|
296
|
+
getBuiltinBundleFilepath,
|
|
297
|
+
getRemoteBundleFilepath,
|
|
298
|
+
loadBuiltinMetadata,
|
|
299
|
+
loadRemoteMetadata,
|
|
300
|
+
unloadDescriptor,
|
|
301
|
+
removeRemoteBundle,
|
|
302
|
+
remoteRetainedVersions,
|
|
303
|
+
pruneRemoteBundles
|
|
304
|
+
};
|
|
305
|
+
//#endregion
|
|
306
|
+
//#region src/updater.ts
|
|
307
|
+
async function listRemotes() {
|
|
308
|
+
return invoke("updaterListRemotes");
|
|
309
|
+
}
|
|
310
|
+
async function getUpdate(bundleName) {
|
|
311
|
+
return invoke("updaterGetUpdate", { bundleName });
|
|
312
|
+
}
|
|
313
|
+
async function download(bundleName, version) {
|
|
314
|
+
return invoke("updaterDownload", {
|
|
315
|
+
bundleName,
|
|
316
|
+
version
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
async function install(bundleName, version) {
|
|
320
|
+
return invoke("updaterInstall", {
|
|
321
|
+
bundleName,
|
|
322
|
+
version
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
const updater = {
|
|
326
|
+
listRemotes,
|
|
327
|
+
getUpdate,
|
|
328
|
+
download,
|
|
329
|
+
install
|
|
330
|
+
};
|
|
331
|
+
//#endregion
|
|
332
|
+
exports.BridgeError = BridgeError;
|
|
333
|
+
exports.BridgeErrorCode = BridgeErrorCode;
|
|
334
|
+
exports.invoke = invoke;
|
|
335
|
+
exports.isBridgeError = isBridgeError;
|
|
336
|
+
exports.isBridgeErrorData = isBridgeErrorData;
|
|
337
|
+
exports.platform = platform;
|
|
338
|
+
exports.remote = remote;
|
|
339
|
+
exports.source = source;
|
|
340
|
+
exports.updater = updater;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { C as isBridgeErrorData, S as isBridgeError, _ as InvokeParams, a as BundleSourceType, b as BridgeErrorCode, c as ListBundleManifestItem, d as ListRemoteBundleInfo, f as RemoteApi, g as platform, h as PlatformType, i as BundleManifestMetadata, l as SourceApi, m as remote, n as UpdaterApi, o as BundleSourceVersion, p as RemoteBundleInfo, r as updater, s as ListBundleItem, t as BundleUpdateInfo, u as source, v as invoke, x as BridgeErrorData, y as BridgeError } from "./index-eeBgJJSy.cjs";
|
|
2
|
+
export { BridgeError, BridgeErrorCode, type BridgeErrorData, type BundleManifestMetadata, type BundleSourceType, type BundleSourceVersion, type BundleUpdateInfo, type InvokeParams, type ListBundleItem, type ListBundleManifestItem, type ListRemoteBundleInfo, type PlatformType, type RemoteApi, type RemoteBundleInfo, type SourceApi, type UpdaterApi, invoke, isBridgeError, isBridgeErrorData, platform, remote, source, updater };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { C as isBridgeErrorData, S as isBridgeError, _ as InvokeParams, a as BundleSourceType, b as BridgeErrorCode, c as ListBundleManifestItem, d as ListRemoteBundleInfo, f as RemoteApi, g as platform, h as PlatformType, i as BundleManifestMetadata, l as SourceApi, m as remote, n as UpdaterApi, o as BundleSourceVersion, p as RemoteBundleInfo, r as updater, s as ListBundleItem, t as BundleUpdateInfo, u as source, v as invoke, x as BridgeErrorData, y as BridgeError } from "./index-eeBgJJSy.js";
|
|
2
|
+
export { BridgeError, BridgeErrorCode, type BridgeErrorData, type BundleManifestMetadata, type BundleSourceType, type BundleSourceVersion, type BundleUpdateInfo, type InvokeParams, type ListBundleItem, type ListBundleManifestItem, type ListRemoteBundleInfo, type PlatformType, type RemoteApi, type RemoteBundleInfo, type SourceApi, type UpdaterApi, invoke, isBridgeError, isBridgeErrorData, platform, remote, source, updater };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { i as _defineProperty, n as INVOKE_MOCK_KEY, r as getWindow, t as PLATFORM_MOCK_KEY } from "./platform-mock-Bvaw9qjP.js";
|
|
2
|
+
import { invoke as invoke$1, isTauri } from "@tauri-apps/api/core";
|
|
3
|
+
//#region src/error.ts
|
|
4
|
+
const BridgeErrorCode = {
|
|
5
|
+
/** `params` was missing or had the wrong shape/type. */
|
|
6
|
+
InvalidParams: "invalid_params",
|
|
7
|
+
/** A `remote.*` command was invoked but no remote is configured. */
|
|
8
|
+
RemoteNotInitialized: "remote_not_initialized",
|
|
9
|
+
/** An `updater.*` command was invoked but no updater is configured. */
|
|
10
|
+
UpdaterNotInitialized: "updater_not_initialized",
|
|
11
|
+
/** No handler is registered for the requested command name. */
|
|
12
|
+
HandlerNotFound: "handler_not_found",
|
|
13
|
+
/** The handler returned a value that is not JSON-encodable. */
|
|
14
|
+
UnencodableResult: "unencodable_result"
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown by `@wvb/bridge` when an `invoke()` command rejects, regardless of
|
|
18
|
+
* platform.
|
|
19
|
+
*/
|
|
20
|
+
var BridgeError = class BridgeError extends Error {
|
|
21
|
+
static of(code, message = "") {
|
|
22
|
+
return new BridgeError({
|
|
23
|
+
code,
|
|
24
|
+
message
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
static from(value) {
|
|
28
|
+
if (value instanceof BridgeError) return value;
|
|
29
|
+
if (isBridgeErrorData(value)) return new BridgeError(value);
|
|
30
|
+
if (value instanceof Error) return new BridgeError({ message: value.message });
|
|
31
|
+
if (typeof value === "string") return new BridgeError({ message: value });
|
|
32
|
+
return new BridgeError({ message: "unknown bridge error" });
|
|
33
|
+
}
|
|
34
|
+
constructor(data) {
|
|
35
|
+
super(data.message);
|
|
36
|
+
_defineProperty(this, "name", "BridgeError");
|
|
37
|
+
_defineProperty(this, "code", void 0);
|
|
38
|
+
this.code = data.code;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function isBridgeError(e) {
|
|
42
|
+
return e != null && typeof e === "object" && "name" in e && e.name === "BridgeError";
|
|
43
|
+
}
|
|
44
|
+
function isBridgeErrorData(value) {
|
|
45
|
+
if (typeof value !== "object" || value === null) return false;
|
|
46
|
+
const data = value;
|
|
47
|
+
return typeof data.message === "string" && (data.code === void 0 || typeof data.code === "string");
|
|
48
|
+
}
|
|
49
|
+
function unknownPlatform() {
|
|
50
|
+
throw new Error("Unknown platform. Make sure native webview supports webview-bundle.");
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/callback.ts
|
|
54
|
+
var CallbackBag = class {
|
|
55
|
+
constructor() {
|
|
56
|
+
_defineProperty(this, "ids", []);
|
|
57
|
+
}
|
|
58
|
+
generate(callback) {
|
|
59
|
+
const w = getWindow();
|
|
60
|
+
w.__wvb_bridge_callbacks__ ?? (w.__wvb_bridge_callbacks__ = {});
|
|
61
|
+
const id = `cb_${generateId()}`;
|
|
62
|
+
w.__wvb_bridge_callbacks__[id] = callback;
|
|
63
|
+
this.ids.push(id);
|
|
64
|
+
return `(
|
|
65
|
+
function() {
|
|
66
|
+
var cb = __wvb_bridge_callbacks__ != null
|
|
67
|
+
? __wvb_bridge_callbacks__["${id}"]
|
|
68
|
+
: undefined;
|
|
69
|
+
if (cb == null) {
|
|
70
|
+
throw new Error("cannot find callback: ${id}");
|
|
71
|
+
}
|
|
72
|
+
return cb.apply(undefined, arguments);
|
|
73
|
+
}
|
|
74
|
+
)`.replace(/(\n|\s{2,})/g, " ");
|
|
75
|
+
}
|
|
76
|
+
clean() {
|
|
77
|
+
const w = getWindow();
|
|
78
|
+
for (const id of this.ids) if (w.__wvb_bridge_callbacks__ != null) Reflect.deleteProperty(w.__wvb_bridge_callbacks__, id);
|
|
79
|
+
this.ids = [];
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
function generateId() {
|
|
83
|
+
const w = getWindow();
|
|
84
|
+
if (typeof w?.crypto?.randomUUID === "function") return w.crypto.randomUUID().replace(/-/g, "");
|
|
85
|
+
const bytes = new Uint8Array(16);
|
|
86
|
+
if (typeof w?.crypto?.getRandomValues === "function") w.crypto.getRandomValues(bytes);
|
|
87
|
+
else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
88
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
89
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
90
|
+
let id = "";
|
|
91
|
+
for (const byte of bytes) id += byte.toString(16).padStart(2, "0");
|
|
92
|
+
return id;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/platform.ts
|
|
96
|
+
function isElectron() {
|
|
97
|
+
return getWindow()?.wvbElectron != null;
|
|
98
|
+
}
|
|
99
|
+
function isAndroid() {
|
|
100
|
+
return getWindow()?.wvbAndroid != null;
|
|
101
|
+
}
|
|
102
|
+
function isIos() {
|
|
103
|
+
return getWindow()?.webkit?.messageHandlers?.wvbIos != null;
|
|
104
|
+
}
|
|
105
|
+
function resolveType() {
|
|
106
|
+
const mocked = getWindow()[PLATFORM_MOCK_KEY];
|
|
107
|
+
if (mocked != null) return mocked;
|
|
108
|
+
if (isElectron()) return "electron";
|
|
109
|
+
if (isTauri()) return "tauri";
|
|
110
|
+
if (isAndroid()) return "android";
|
|
111
|
+
if (isIos()) return "ios";
|
|
112
|
+
}
|
|
113
|
+
const platform = {
|
|
114
|
+
get type() {
|
|
115
|
+
return resolveType();
|
|
116
|
+
},
|
|
117
|
+
get isElectron() {
|
|
118
|
+
return resolveType() === "electron";
|
|
119
|
+
},
|
|
120
|
+
get isTauri() {
|
|
121
|
+
return resolveType() === "tauri";
|
|
122
|
+
},
|
|
123
|
+
get isAndroid() {
|
|
124
|
+
return resolveType() === "android";
|
|
125
|
+
},
|
|
126
|
+
get isIos() {
|
|
127
|
+
return resolveType() === "ios";
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/utils.ts
|
|
132
|
+
function snakeCase(str) {
|
|
133
|
+
return str.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").trim().replace(/ /g, "_").toLowerCase();
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/invoke.ts
|
|
137
|
+
/**
|
|
138
|
+
* Invokes a native bridge command and resolves its result.
|
|
139
|
+
* Before using the bridge, make sure native supports webview-bundle.
|
|
140
|
+
*
|
|
141
|
+
* Throws a {@link BridgeError} on failure.
|
|
142
|
+
*/
|
|
143
|
+
async function invoke(name, params) {
|
|
144
|
+
try {
|
|
145
|
+
return await invokeInner(name, params);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
throw BridgeError.from(error);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function invokeInner(name, params) {
|
|
151
|
+
const mock = getWindow()[INVOKE_MOCK_KEY];
|
|
152
|
+
if (mock != null) return mock(name, params);
|
|
153
|
+
switch (platform.type) {
|
|
154
|
+
case "electron": return getWindow().wvbElectron.invoke(name, params);
|
|
155
|
+
case "tauri": return invoke$1(toTauriCommand(name), params);
|
|
156
|
+
case "android":
|
|
157
|
+
case "ios": {
|
|
158
|
+
const bridge = getMobileBridge(platform.type);
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
const bag = new CallbackBag();
|
|
161
|
+
const success = bag.generate((result) => {
|
|
162
|
+
resolve(result);
|
|
163
|
+
bag.clean();
|
|
164
|
+
});
|
|
165
|
+
const error = bag.generate((error) => {
|
|
166
|
+
reject(error);
|
|
167
|
+
bag.clean();
|
|
168
|
+
});
|
|
169
|
+
try {
|
|
170
|
+
bridge.postMessage(name, params, success, error);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
bag.clean();
|
|
173
|
+
reject(error);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
default: unknownPlatform();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function getMobileBridge(platform) {
|
|
181
|
+
switch (platform) {
|
|
182
|
+
case "android": {
|
|
183
|
+
const w = getWindow();
|
|
184
|
+
return { postMessage: (name, params, success, error) => w.wvbAndroid.postMessage(JSON.stringify({
|
|
185
|
+
name,
|
|
186
|
+
params,
|
|
187
|
+
success,
|
|
188
|
+
error
|
|
189
|
+
})) };
|
|
190
|
+
}
|
|
191
|
+
case "ios": {
|
|
192
|
+
const w = getWindow();
|
|
193
|
+
return { postMessage: (name, params, success, error) => w.webkit.messageHandlers.wvbIos.postMessage({
|
|
194
|
+
name,
|
|
195
|
+
params,
|
|
196
|
+
success,
|
|
197
|
+
error
|
|
198
|
+
}) };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function toTauriCommand(name) {
|
|
203
|
+
return `plugin:wvb-tauri|${snakeCase(name)}`;
|
|
204
|
+
}
|
|
205
|
+
//#endregion
|
|
206
|
+
//#region src/remote.ts
|
|
207
|
+
async function listBundles$1(channel) {
|
|
208
|
+
return invoke("remoteListBundles", { channel });
|
|
209
|
+
}
|
|
210
|
+
async function getInfo(bundleName, channel) {
|
|
211
|
+
return invoke("remoteGetInfo", {
|
|
212
|
+
bundleName,
|
|
213
|
+
channel
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
async function download$1(bundleName, channel) {
|
|
217
|
+
return invoke("remoteDownload", {
|
|
218
|
+
bundleName,
|
|
219
|
+
channel
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async function downloadVersion(bundleName, version) {
|
|
223
|
+
return invoke("remoteDownloadVersion", {
|
|
224
|
+
bundleName,
|
|
225
|
+
version
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
const remote = {
|
|
229
|
+
listBundles: listBundles$1,
|
|
230
|
+
getInfo,
|
|
231
|
+
download: download$1,
|
|
232
|
+
downloadVersion
|
|
233
|
+
};
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/source.ts
|
|
236
|
+
async function listBundles() {
|
|
237
|
+
return invoke("sourceListBundles");
|
|
238
|
+
}
|
|
239
|
+
async function loadVersion(bundleName) {
|
|
240
|
+
return invoke("sourceLoadVersion", { bundleName });
|
|
241
|
+
}
|
|
242
|
+
async function updateVersion(bundleName, version) {
|
|
243
|
+
return invoke("sourceUpdateVersion", {
|
|
244
|
+
bundleName,
|
|
245
|
+
version
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
async function resolveFilepath(bundleName) {
|
|
249
|
+
return invoke("sourceResolveFilepath", { bundleName });
|
|
250
|
+
}
|
|
251
|
+
async function getBuiltinBundleFilepath(bundleName, version) {
|
|
252
|
+
return invoke("sourceGetBuiltinBundleFilepath", {
|
|
253
|
+
bundleName,
|
|
254
|
+
version
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
async function getRemoteBundleFilepath(bundleName, version) {
|
|
258
|
+
return invoke("sourceGetRemoteBundleFilepath", {
|
|
259
|
+
bundleName,
|
|
260
|
+
version
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
async function loadBuiltinMetadata(bundleName, version) {
|
|
264
|
+
return invoke("sourceLoadBuiltinMetadata", {
|
|
265
|
+
bundleName,
|
|
266
|
+
version
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
async function loadRemoteMetadata(bundleName, version) {
|
|
270
|
+
return invoke("sourceLoadRemoteMetadata", {
|
|
271
|
+
bundleName,
|
|
272
|
+
version
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
async function unloadDescriptor(bundleName) {
|
|
276
|
+
return invoke("sourceUnloadDescriptor", { bundleName });
|
|
277
|
+
}
|
|
278
|
+
async function removeRemoteBundle(bundleName, version) {
|
|
279
|
+
return invoke("sourceRemoveRemoteBundle", {
|
|
280
|
+
bundleName,
|
|
281
|
+
version
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
async function remoteRetainedVersions(bundleName) {
|
|
285
|
+
return invoke("sourceRemoteRetainedVersions", { bundleName });
|
|
286
|
+
}
|
|
287
|
+
async function pruneRemoteBundles(bundleName) {
|
|
288
|
+
return invoke("sourcePruneRemoteBundles", { bundleName });
|
|
289
|
+
}
|
|
290
|
+
const source = {
|
|
291
|
+
listBundles,
|
|
292
|
+
loadVersion,
|
|
293
|
+
updateVersion,
|
|
294
|
+
resolveFilepath,
|
|
295
|
+
getBuiltinBundleFilepath,
|
|
296
|
+
getRemoteBundleFilepath,
|
|
297
|
+
loadBuiltinMetadata,
|
|
298
|
+
loadRemoteMetadata,
|
|
299
|
+
unloadDescriptor,
|
|
300
|
+
removeRemoteBundle,
|
|
301
|
+
remoteRetainedVersions,
|
|
302
|
+
pruneRemoteBundles
|
|
303
|
+
};
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/updater.ts
|
|
306
|
+
async function listRemotes() {
|
|
307
|
+
return invoke("updaterListRemotes");
|
|
308
|
+
}
|
|
309
|
+
async function getUpdate(bundleName) {
|
|
310
|
+
return invoke("updaterGetUpdate", { bundleName });
|
|
311
|
+
}
|
|
312
|
+
async function download(bundleName, version) {
|
|
313
|
+
return invoke("updaterDownload", {
|
|
314
|
+
bundleName,
|
|
315
|
+
version
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
async function install(bundleName, version) {
|
|
319
|
+
return invoke("updaterInstall", {
|
|
320
|
+
bundleName,
|
|
321
|
+
version
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
const updater = {
|
|
325
|
+
listRemotes,
|
|
326
|
+
getUpdate,
|
|
327
|
+
download,
|
|
328
|
+
install
|
|
329
|
+
};
|
|
330
|
+
//#endregion
|
|
331
|
+
export { BridgeError, BridgeErrorCode, invoke, isBridgeError, isBridgeErrorData, platform, remote, source, updater };
|