@wvb/bridge 0.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/CHANGELOG.md +1 -0
- package/README.md +1 -0
- package/dist/index-B2ggQzrN.d.cts +162 -0
- package/dist/index-B2ggQzrN.d.ts +162 -0
- package/dist/index.cjs +278 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +273 -0
- package/dist/platform-mock-BmiQzf2l.cjs +73 -0
- package/dist/platform-mock-Dh3dBF3P.js +50 -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.js
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { i as getWindow, n as INVOKE_MOCK_KEY, r as _defineProperty, t as PLATFORM_MOCK_KEY } from "./platform-mock-Dh3dBF3P.js";
|
|
2
|
+
import { invoke as invoke$1, isTauri } from "@tauri-apps/api/core";
|
|
3
|
+
//#region src/callback.ts
|
|
4
|
+
var CallbackBag = class {
|
|
5
|
+
constructor() {
|
|
6
|
+
_defineProperty(this, "ids", []);
|
|
7
|
+
}
|
|
8
|
+
generate(callback) {
|
|
9
|
+
const w = getWindow();
|
|
10
|
+
w.__wvb_bridge_callbacks__ ?? (w.__wvb_bridge_callbacks__ = {});
|
|
11
|
+
const id = `cb_${generateId()}`;
|
|
12
|
+
w.__wvb_bridge_callbacks__[id] = callback;
|
|
13
|
+
this.ids.push(id);
|
|
14
|
+
return `(
|
|
15
|
+
function() {
|
|
16
|
+
var cb = __wvb_bridge_callbacks__ != null
|
|
17
|
+
? __wvb_bridge_callbacks__["${id}"]
|
|
18
|
+
: undefined;
|
|
19
|
+
if (cb == null) {
|
|
20
|
+
throw new Error("cannot find callback: ${id}");
|
|
21
|
+
}
|
|
22
|
+
return cb.apply(undefined, arguments);
|
|
23
|
+
}
|
|
24
|
+
)`.replace(/(\n|\s{2,})/g, " ");
|
|
25
|
+
}
|
|
26
|
+
clean() {
|
|
27
|
+
const w = getWindow();
|
|
28
|
+
for (const id of this.ids) if (w.__wvb_bridge_callbacks__ != null) Reflect.deleteProperty(w.__wvb_bridge_callbacks__, id);
|
|
29
|
+
this.ids = [];
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function generateId() {
|
|
33
|
+
const w = getWindow();
|
|
34
|
+
if (typeof w?.crypto?.randomUUID === "function") return w.crypto.randomUUID().replace(/-/g, "");
|
|
35
|
+
const bytes = new Uint8Array(16);
|
|
36
|
+
if (typeof w?.crypto?.getRandomValues === "function") w.crypto.getRandomValues(bytes);
|
|
37
|
+
else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
38
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
39
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
40
|
+
let id = "";
|
|
41
|
+
for (const byte of bytes) id += byte.toString(16).padStart(2, "0");
|
|
42
|
+
return id;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/error.ts
|
|
46
|
+
function unknownPlatform() {
|
|
47
|
+
throw new Error("Unknown platform. Make sure native webview supports webview-bundle.");
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/platform.ts
|
|
51
|
+
function isElectron() {
|
|
52
|
+
return getWindow()?.wvbElectron != null;
|
|
53
|
+
}
|
|
54
|
+
function isAndroid() {
|
|
55
|
+
return getWindow()?.wvbAndroid != null;
|
|
56
|
+
}
|
|
57
|
+
function isIos() {
|
|
58
|
+
return getWindow()?.webkit?.messageHandlers?.wvbIos != null;
|
|
59
|
+
}
|
|
60
|
+
function resolveType() {
|
|
61
|
+
const mocked = getWindow()[PLATFORM_MOCK_KEY];
|
|
62
|
+
if (mocked != null) return mocked;
|
|
63
|
+
if (isElectron()) return "electron";
|
|
64
|
+
if (isTauri()) return "tauri";
|
|
65
|
+
if (isAndroid()) return "android";
|
|
66
|
+
if (isIos()) return "ios";
|
|
67
|
+
}
|
|
68
|
+
const platform = {
|
|
69
|
+
get type() {
|
|
70
|
+
return resolveType();
|
|
71
|
+
},
|
|
72
|
+
get isElectron() {
|
|
73
|
+
return resolveType() === "electron";
|
|
74
|
+
},
|
|
75
|
+
get isTauri() {
|
|
76
|
+
return resolveType() === "tauri";
|
|
77
|
+
},
|
|
78
|
+
get isAndroid() {
|
|
79
|
+
return resolveType() === "android";
|
|
80
|
+
},
|
|
81
|
+
get isIos() {
|
|
82
|
+
return resolveType() === "ios";
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/utils.ts
|
|
87
|
+
function snakeCase(str) {
|
|
88
|
+
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();
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/invoke.ts
|
|
92
|
+
function invoke(name, params) {
|
|
93
|
+
const mock = getWindow()[INVOKE_MOCK_KEY];
|
|
94
|
+
if (mock != null) return mock(name, params);
|
|
95
|
+
switch (platform.type) {
|
|
96
|
+
case "electron": return getWindow().wvbElectron.invoke(name, params);
|
|
97
|
+
case "tauri": return invoke$1(toTauriCommand(name), params);
|
|
98
|
+
case "android":
|
|
99
|
+
case "ios": {
|
|
100
|
+
const bridge = getMobileBridge(platform.type);
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
const bag = new CallbackBag();
|
|
103
|
+
const success = bag.generate((result) => {
|
|
104
|
+
resolve(result);
|
|
105
|
+
bag.clean();
|
|
106
|
+
});
|
|
107
|
+
const error = bag.generate((error) => {
|
|
108
|
+
reject(error);
|
|
109
|
+
bag.clean();
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
bridge.postMessage(name, params, success, error);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
bag.clean();
|
|
115
|
+
reject(error);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
default: unknownPlatform();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function getMobileBridge(platform) {
|
|
123
|
+
switch (platform) {
|
|
124
|
+
case "android": {
|
|
125
|
+
const w = getWindow();
|
|
126
|
+
return { postMessage: (name, params, success, error) => w.wvbAndroid.postMessage(JSON.stringify({
|
|
127
|
+
name,
|
|
128
|
+
params,
|
|
129
|
+
success,
|
|
130
|
+
error
|
|
131
|
+
})) };
|
|
132
|
+
}
|
|
133
|
+
case "ios": {
|
|
134
|
+
const w = getWindow();
|
|
135
|
+
return { postMessage: (name, params, success, error) => w.webkit.messageHandlers.wvbIos.postMessage({
|
|
136
|
+
name,
|
|
137
|
+
params,
|
|
138
|
+
success,
|
|
139
|
+
error
|
|
140
|
+
}) };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function toTauriCommand(name) {
|
|
145
|
+
return `plugin:wvb-tauri|${snakeCase(name)}`;
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
148
|
+
//#region src/remote.ts
|
|
149
|
+
async function listBundles$1(channel) {
|
|
150
|
+
return invoke("remoteListBundles", { channel });
|
|
151
|
+
}
|
|
152
|
+
async function getInfo(bundleName, channel) {
|
|
153
|
+
return invoke("remoteGetInfo", {
|
|
154
|
+
bundleName,
|
|
155
|
+
channel
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async function download$1(bundleName, channel) {
|
|
159
|
+
return invoke("remoteDownload", {
|
|
160
|
+
bundleName,
|
|
161
|
+
channel
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
async function downloadVersion(bundleName, version) {
|
|
165
|
+
return invoke("remoteDownloadVersion", {
|
|
166
|
+
bundleName,
|
|
167
|
+
version
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
const remote = {
|
|
171
|
+
listBundles: listBundles$1,
|
|
172
|
+
getInfo,
|
|
173
|
+
download: download$1,
|
|
174
|
+
downloadVersion
|
|
175
|
+
};
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/source.ts
|
|
178
|
+
async function listBundles() {
|
|
179
|
+
return invoke("sourceListBundles");
|
|
180
|
+
}
|
|
181
|
+
async function loadVersion(bundleName) {
|
|
182
|
+
return invoke("sourceLoadVersion", { bundleName });
|
|
183
|
+
}
|
|
184
|
+
async function updateVersion(bundleName, version) {
|
|
185
|
+
return invoke("sourceUpdateVersion", {
|
|
186
|
+
bundleName,
|
|
187
|
+
version
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
async function resolveFilepath(bundleName) {
|
|
191
|
+
return invoke("sourceResolveFilepath", { bundleName });
|
|
192
|
+
}
|
|
193
|
+
async function getBuiltinBundleFilepath(bundleName, version) {
|
|
194
|
+
return invoke("sourceGetBuiltinBundleFilepath", {
|
|
195
|
+
bundleName,
|
|
196
|
+
version
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
async function getRemoteBundleFilepath(bundleName, version) {
|
|
200
|
+
return invoke("sourceGetRemoteBundleFilepath", {
|
|
201
|
+
bundleName,
|
|
202
|
+
version
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
async function loadBuiltinMetadata(bundleName, version) {
|
|
206
|
+
return invoke("sourceLoadBuiltinMetadata", {
|
|
207
|
+
bundleName,
|
|
208
|
+
version
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
async function loadRemoteMetadata(bundleName, version) {
|
|
212
|
+
return invoke("sourceLoadRemoteMetadata", {
|
|
213
|
+
bundleName,
|
|
214
|
+
version
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
async function unloadDescriptor(bundleName) {
|
|
218
|
+
return invoke("sourceUnloadDescriptor", { bundleName });
|
|
219
|
+
}
|
|
220
|
+
async function removeRemoteBundle(bundleName, version) {
|
|
221
|
+
return invoke("sourceRemoveRemoteBundle", {
|
|
222
|
+
bundleName,
|
|
223
|
+
version
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
async function remoteRetainedVersions(bundleName) {
|
|
227
|
+
return invoke("sourceRemoteRetainedVersions", { bundleName });
|
|
228
|
+
}
|
|
229
|
+
async function pruneRemoteBundles(bundleName) {
|
|
230
|
+
return invoke("sourcePruneRemoteBundles", { bundleName });
|
|
231
|
+
}
|
|
232
|
+
const source = {
|
|
233
|
+
listBundles,
|
|
234
|
+
loadVersion,
|
|
235
|
+
updateVersion,
|
|
236
|
+
resolveFilepath,
|
|
237
|
+
getBuiltinBundleFilepath,
|
|
238
|
+
getRemoteBundleFilepath,
|
|
239
|
+
loadBuiltinMetadata,
|
|
240
|
+
loadRemoteMetadata,
|
|
241
|
+
unloadDescriptor,
|
|
242
|
+
removeRemoteBundle,
|
|
243
|
+
remoteRetainedVersions,
|
|
244
|
+
pruneRemoteBundles
|
|
245
|
+
};
|
|
246
|
+
//#endregion
|
|
247
|
+
//#region src/updater.ts
|
|
248
|
+
async function listRemotes() {
|
|
249
|
+
return invoke("updaterListRemotes");
|
|
250
|
+
}
|
|
251
|
+
async function getUpdate(bundleName) {
|
|
252
|
+
return invoke("updaterGetUpdate", { bundleName });
|
|
253
|
+
}
|
|
254
|
+
async function download(bundleName, version) {
|
|
255
|
+
return invoke("updaterDownload", {
|
|
256
|
+
bundleName,
|
|
257
|
+
version
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
async function install(bundleName, version) {
|
|
261
|
+
return invoke("updaterInstall", {
|
|
262
|
+
bundleName,
|
|
263
|
+
version
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
const updater = {
|
|
267
|
+
listRemotes,
|
|
268
|
+
getUpdate,
|
|
269
|
+
download,
|
|
270
|
+
install
|
|
271
|
+
};
|
|
272
|
+
//#endregion
|
|
273
|
+
export { invoke, platform, remote, source, updater };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//#region src/window.ts
|
|
2
|
+
function getWindow() {
|
|
3
|
+
return globalThis || window;
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/typeof.js
|
|
7
|
+
function _typeof(o) {
|
|
8
|
+
"@babel/helpers - typeof";
|
|
9
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
10
|
+
return typeof o;
|
|
11
|
+
} : function(o) {
|
|
12
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
13
|
+
}, _typeof(o);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPrimitive.js
|
|
17
|
+
function toPrimitive(t, r) {
|
|
18
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
19
|
+
var e = t[Symbol.toPrimitive];
|
|
20
|
+
if (void 0 !== e) {
|
|
21
|
+
var i = e.call(t, r || "default");
|
|
22
|
+
if ("object" != _typeof(i)) return i;
|
|
23
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
24
|
+
}
|
|
25
|
+
return ("string" === r ? String : Number)(t);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPropertyKey.js
|
|
29
|
+
function toPropertyKey(t) {
|
|
30
|
+
var i = toPrimitive(t, "string");
|
|
31
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/defineProperty.js
|
|
35
|
+
function _defineProperty(e, r, t) {
|
|
36
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
37
|
+
value: t,
|
|
38
|
+
enumerable: !0,
|
|
39
|
+
configurable: !0,
|
|
40
|
+
writable: !0
|
|
41
|
+
}) : e[r] = t, e;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/invoke-mock.ts
|
|
45
|
+
const INVOKE_MOCK_KEY = "__wvb_invoke_mock__";
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/platform-mock.ts
|
|
48
|
+
const PLATFORM_MOCK_KEY = "__wvb_platform_mock__";
|
|
49
|
+
//#endregion
|
|
50
|
+
Object.defineProperty(exports, "INVOKE_MOCK_KEY", {
|
|
51
|
+
enumerable: true,
|
|
52
|
+
get: function() {
|
|
53
|
+
return INVOKE_MOCK_KEY;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
Object.defineProperty(exports, "PLATFORM_MOCK_KEY", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function() {
|
|
59
|
+
return PLATFORM_MOCK_KEY;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
Object.defineProperty(exports, "_defineProperty", {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
get: function() {
|
|
65
|
+
return _defineProperty;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
Object.defineProperty(exports, "getWindow", {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function() {
|
|
71
|
+
return getWindow;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/window.ts
|
|
2
|
+
function getWindow() {
|
|
3
|
+
return globalThis || window;
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/typeof.js
|
|
7
|
+
function _typeof(o) {
|
|
8
|
+
"@babel/helpers - typeof";
|
|
9
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
10
|
+
return typeof o;
|
|
11
|
+
} : function(o) {
|
|
12
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
13
|
+
}, _typeof(o);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPrimitive.js
|
|
17
|
+
function toPrimitive(t, r) {
|
|
18
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
19
|
+
var e = t[Symbol.toPrimitive];
|
|
20
|
+
if (void 0 !== e) {
|
|
21
|
+
var i = e.call(t, r || "default");
|
|
22
|
+
if ("object" != _typeof(i)) return i;
|
|
23
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
24
|
+
}
|
|
25
|
+
return ("string" === r ? String : Number)(t);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPropertyKey.js
|
|
29
|
+
function toPropertyKey(t) {
|
|
30
|
+
var i = toPrimitive(t, "string");
|
|
31
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/defineProperty.js
|
|
35
|
+
function _defineProperty(e, r, t) {
|
|
36
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
37
|
+
value: t,
|
|
38
|
+
enumerable: !0,
|
|
39
|
+
configurable: !0,
|
|
40
|
+
writable: !0
|
|
41
|
+
}) : e[r] = t, e;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/invoke-mock.ts
|
|
45
|
+
const INVOKE_MOCK_KEY = "__wvb_invoke_mock__";
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/platform-mock.ts
|
|
48
|
+
const PLATFORM_MOCK_KEY = "__wvb_platform_mock__";
|
|
49
|
+
//#endregion
|
|
50
|
+
export { getWindow as i, INVOKE_MOCK_KEY as n, _defineProperty as r, PLATFORM_MOCK_KEY as t };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_platform_mock = require("../platform-mock-BmiQzf2l.cjs");
|
|
3
|
+
//#region src/testing/mock.ts
|
|
4
|
+
const store = /* @__PURE__ */ new Map();
|
|
5
|
+
function ensureMocked() {
|
|
6
|
+
const w = require_platform_mock.getWindow();
|
|
7
|
+
if (w["__wvb_invoke_mock__"] != null) return;
|
|
8
|
+
w[require_platform_mock.INVOKE_MOCK_KEY] = (name, params) => {
|
|
9
|
+
const handler = store.get(name);
|
|
10
|
+
if (handler == null) return Promise.reject(/* @__PURE__ */ new Error(`[@wvb/bridge/testing] no mock registered for invoke "${name}"`));
|
|
11
|
+
const args = params == null ? [] : Object.values(params);
|
|
12
|
+
return Promise.resolve().then(() => handler(...args));
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function toInvokeName(command) {
|
|
16
|
+
const [namespace = "", method = ""] = command.split(".");
|
|
17
|
+
return `${namespace}${method.charAt(0).toUpperCase()}${method.slice(1)}`;
|
|
18
|
+
}
|
|
19
|
+
function registerMockInvoke(command, handler) {
|
|
20
|
+
ensureMocked();
|
|
21
|
+
const name = toInvokeName(command);
|
|
22
|
+
store.set(name, handler);
|
|
23
|
+
const clear = () => {
|
|
24
|
+
if (store.get(name) === handler) store.delete(name);
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
clear,
|
|
28
|
+
[Symbol.dispose]: clear
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function clearInvokeMocks() {
|
|
32
|
+
store.clear();
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/testing/index.ts
|
|
36
|
+
let _Symbol$dispose;
|
|
37
|
+
/**
|
|
38
|
+
* Registers a mock handler that responds a single bridge `invoke` command.
|
|
39
|
+
*
|
|
40
|
+
* Returns a `MockInvoke` (a `Disposable`): declare it with `using` to clear the mock
|
|
41
|
+
* automatically when the scope exits, call `.clear()` to remove it manually, or let it
|
|
42
|
+
* persist until {@link clearInvokeMocks}.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { source } from '@wvb/bridge';
|
|
47
|
+
* import { mockInvoke } from '@wvb/bridge/testing';
|
|
48
|
+
* import { expect, test } from 'vitest';
|
|
49
|
+
*
|
|
50
|
+
* test('loads the active version', async () => {
|
|
51
|
+
* using _mock = mockInvoke('source.loadVersion', bundleName => {
|
|
52
|
+
* expect(bundleName).toBe('app');
|
|
53
|
+
* return { type: 'remote', version: '1.0.0' };
|
|
54
|
+
* });
|
|
55
|
+
* await expect(source.loadVersion('app')).resolves.toEqual({ type: 'remote', version: '1.0.0' });
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
function mockInvoke(command, handler) {
|
|
60
|
+
return registerMockInvoke(command, handler);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Mock platform type.
|
|
64
|
+
*/
|
|
65
|
+
function mockPlatform(type) {
|
|
66
|
+
const host = require_platform_mock.getWindow();
|
|
67
|
+
const previous = host[require_platform_mock.PLATFORM_MOCK_KEY];
|
|
68
|
+
host[require_platform_mock.PLATFORM_MOCK_KEY] = type;
|
|
69
|
+
return { [Symbol.dispose]() {
|
|
70
|
+
host[require_platform_mock.PLATFORM_MOCK_KEY] = previous;
|
|
71
|
+
} };
|
|
72
|
+
}
|
|
73
|
+
_Symbol$dispose = Symbol.dispose;
|
|
74
|
+
var MockBridgeImpl = class {
|
|
75
|
+
constructor(options) {
|
|
76
|
+
require_platform_mock._defineProperty(this, "disposables", []);
|
|
77
|
+
if (options?.platform != null) this.disposables.push(mockPlatform(options.platform));
|
|
78
|
+
}
|
|
79
|
+
mockInvoke(command, handler) {
|
|
80
|
+
this.disposables.push(mockInvoke(command, handler));
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
clear() {
|
|
84
|
+
for (const disposable of this.disposables.reverse()) disposable[Symbol.dispose]();
|
|
85
|
+
this.disposables = [];
|
|
86
|
+
}
|
|
87
|
+
[_Symbol$dispose]() {
|
|
88
|
+
this.clear();
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Create a mock bridge instance.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* import { source } from '@wvb/bridge';
|
|
97
|
+
* import { mockBridge } from '@wvb/bridge/testing';
|
|
98
|
+
* import { expect, test } from 'vitest';
|
|
99
|
+
*
|
|
100
|
+
* test('loads the active version', async () => {
|
|
101
|
+
* using bridge = mockBridge()
|
|
102
|
+
* .mockInvoke('source.loadVersion', bundleName => {
|
|
103
|
+
* expect(bundleName).toBe('app');
|
|
104
|
+
* return { type: 'remote', version: '1.0.0' };
|
|
105
|
+
* });
|
|
106
|
+
*
|
|
107
|
+
* await expect(source.loadVersion('app')).resolves.toEqual({ type: 'remote', version: '1.0.0' });
|
|
108
|
+
* });
|
|
109
|
+
*/
|
|
110
|
+
function mockBridge(options) {
|
|
111
|
+
return new MockBridgeImpl(options);
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
exports.clearInvokeMocks = clearInvokeMocks;
|
|
115
|
+
exports.mockBridge = mockBridge;
|
|
116
|
+
exports.mockInvoke = mockInvoke;
|
|
117
|
+
exports.mockPlatform = mockPlatform;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { f as RemoteApi, h as PlatformType, l as SourceApi, n as UpdaterApi } from "../index-B2ggQzrN.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/testing/mock.d.ts
|
|
4
|
+
interface MockInvoke extends Disposable {
|
|
5
|
+
clear(): void;
|
|
6
|
+
}
|
|
7
|
+
declare function clearInvokeMocks(): void;
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/testing/typesmap.d.ts
|
|
10
|
+
type Commands<Namespace extends string, Api> = { [K in keyof Api as `${Namespace}.${K & string}`]: Api[K] extends ((...args: infer P) => infer R) ? {
|
|
11
|
+
params: P;
|
|
12
|
+
result: Awaited<R>;
|
|
13
|
+
} : never };
|
|
14
|
+
type BridgeCommandMap = Commands<"source", SourceApi> & Commands<"remote", RemoteApi> & Commands<"updater", UpdaterApi>;
|
|
15
|
+
type MockInvokeCommand = keyof BridgeCommandMap;
|
|
16
|
+
type MockInvokeHandler<K extends MockInvokeCommand> = (...params: BridgeCommandMap[K]["params"]) => BridgeCommandMap[K]["result"] | Promise<BridgeCommandMap[K]["result"]>;
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/testing/index.d.ts
|
|
19
|
+
/**
|
|
20
|
+
* Registers a mock handler that responds a single bridge `invoke` command.
|
|
21
|
+
*
|
|
22
|
+
* Returns a `MockInvoke` (a `Disposable`): declare it with `using` to clear the mock
|
|
23
|
+
* automatically when the scope exits, call `.clear()` to remove it manually, or let it
|
|
24
|
+
* persist until {@link clearInvokeMocks}.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { source } from '@wvb/bridge';
|
|
29
|
+
* import { mockInvoke } from '@wvb/bridge/testing';
|
|
30
|
+
* import { expect, test } from 'vitest';
|
|
31
|
+
*
|
|
32
|
+
* test('loads the active version', async () => {
|
|
33
|
+
* using _mock = mockInvoke('source.loadVersion', bundleName => {
|
|
34
|
+
* expect(bundleName).toBe('app');
|
|
35
|
+
* return { type: 'remote', version: '1.0.0' };
|
|
36
|
+
* });
|
|
37
|
+
* await expect(source.loadVersion('app')).resolves.toEqual({ type: 'remote', version: '1.0.0' });
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
declare function mockInvoke<K extends MockInvokeCommand>(command: K, handler: MockInvokeHandler<K>): MockInvoke;
|
|
42
|
+
/**
|
|
43
|
+
* Mock platform type.
|
|
44
|
+
*/
|
|
45
|
+
declare function mockPlatform(type: PlatformType): Disposable;
|
|
46
|
+
interface MockBridge extends Disposable {
|
|
47
|
+
mockInvoke<K extends MockInvokeCommand>(command: K, handler: MockInvokeHandler<K>): this;
|
|
48
|
+
clear(): void;
|
|
49
|
+
}
|
|
50
|
+
interface MockBridgeOptions {
|
|
51
|
+
/** Platform type to mock. */
|
|
52
|
+
platform?: PlatformType;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a mock bridge instance.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { source } from '@wvb/bridge';
|
|
60
|
+
* import { mockBridge } from '@wvb/bridge/testing';
|
|
61
|
+
* import { expect, test } from 'vitest';
|
|
62
|
+
*
|
|
63
|
+
* test('loads the active version', async () => {
|
|
64
|
+
* using bridge = mockBridge()
|
|
65
|
+
* .mockInvoke('source.loadVersion', bundleName => {
|
|
66
|
+
* expect(bundleName).toBe('app');
|
|
67
|
+
* return { type: 'remote', version: '1.0.0' };
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* await expect(source.loadVersion('app')).resolves.toEqual({ type: 'remote', version: '1.0.0' });
|
|
71
|
+
* });
|
|
72
|
+
*/
|
|
73
|
+
declare function mockBridge(options?: MockBridgeOptions): MockBridge;
|
|
74
|
+
//#endregion
|
|
75
|
+
export { type BridgeCommandMap, MockBridge, MockBridgeOptions, type MockInvoke, type MockInvokeCommand, type MockInvokeHandler, clearInvokeMocks, mockBridge, mockInvoke, mockPlatform };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { f as RemoteApi, h as PlatformType, l as SourceApi, n as UpdaterApi } from "../index-B2ggQzrN.js";
|
|
2
|
+
|
|
3
|
+
//#region src/testing/mock.d.ts
|
|
4
|
+
interface MockInvoke extends Disposable {
|
|
5
|
+
clear(): void;
|
|
6
|
+
}
|
|
7
|
+
declare function clearInvokeMocks(): void;
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/testing/typesmap.d.ts
|
|
10
|
+
type Commands<Namespace extends string, Api> = { [K in keyof Api as `${Namespace}.${K & string}`]: Api[K] extends ((...args: infer P) => infer R) ? {
|
|
11
|
+
params: P;
|
|
12
|
+
result: Awaited<R>;
|
|
13
|
+
} : never };
|
|
14
|
+
type BridgeCommandMap = Commands<"source", SourceApi> & Commands<"remote", RemoteApi> & Commands<"updater", UpdaterApi>;
|
|
15
|
+
type MockInvokeCommand = keyof BridgeCommandMap;
|
|
16
|
+
type MockInvokeHandler<K extends MockInvokeCommand> = (...params: BridgeCommandMap[K]["params"]) => BridgeCommandMap[K]["result"] | Promise<BridgeCommandMap[K]["result"]>;
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/testing/index.d.ts
|
|
19
|
+
/**
|
|
20
|
+
* Registers a mock handler that responds a single bridge `invoke` command.
|
|
21
|
+
*
|
|
22
|
+
* Returns a `MockInvoke` (a `Disposable`): declare it with `using` to clear the mock
|
|
23
|
+
* automatically when the scope exits, call `.clear()` to remove it manually, or let it
|
|
24
|
+
* persist until {@link clearInvokeMocks}.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { source } from '@wvb/bridge';
|
|
29
|
+
* import { mockInvoke } from '@wvb/bridge/testing';
|
|
30
|
+
* import { expect, test } from 'vitest';
|
|
31
|
+
*
|
|
32
|
+
* test('loads the active version', async () => {
|
|
33
|
+
* using _mock = mockInvoke('source.loadVersion', bundleName => {
|
|
34
|
+
* expect(bundleName).toBe('app');
|
|
35
|
+
* return { type: 'remote', version: '1.0.0' };
|
|
36
|
+
* });
|
|
37
|
+
* await expect(source.loadVersion('app')).resolves.toEqual({ type: 'remote', version: '1.0.0' });
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
declare function mockInvoke<K extends MockInvokeCommand>(command: K, handler: MockInvokeHandler<K>): MockInvoke;
|
|
42
|
+
/**
|
|
43
|
+
* Mock platform type.
|
|
44
|
+
*/
|
|
45
|
+
declare function mockPlatform(type: PlatformType): Disposable;
|
|
46
|
+
interface MockBridge extends Disposable {
|
|
47
|
+
mockInvoke<K extends MockInvokeCommand>(command: K, handler: MockInvokeHandler<K>): this;
|
|
48
|
+
clear(): void;
|
|
49
|
+
}
|
|
50
|
+
interface MockBridgeOptions {
|
|
51
|
+
/** Platform type to mock. */
|
|
52
|
+
platform?: PlatformType;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a mock bridge instance.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { source } from '@wvb/bridge';
|
|
60
|
+
* import { mockBridge } from '@wvb/bridge/testing';
|
|
61
|
+
* import { expect, test } from 'vitest';
|
|
62
|
+
*
|
|
63
|
+
* test('loads the active version', async () => {
|
|
64
|
+
* using bridge = mockBridge()
|
|
65
|
+
* .mockInvoke('source.loadVersion', bundleName => {
|
|
66
|
+
* expect(bundleName).toBe('app');
|
|
67
|
+
* return { type: 'remote', version: '1.0.0' };
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* await expect(source.loadVersion('app')).resolves.toEqual({ type: 'remote', version: '1.0.0' });
|
|
71
|
+
* });
|
|
72
|
+
*/
|
|
73
|
+
declare function mockBridge(options?: MockBridgeOptions): MockBridge;
|
|
74
|
+
//#endregion
|
|
75
|
+
export { type BridgeCommandMap, MockBridge, MockBridgeOptions, type MockInvoke, type MockInvokeCommand, type MockInvokeHandler, clearInvokeMocks, mockBridge, mockInvoke, mockPlatform };
|