@iyexin/mio-api 0.0.0-stage → 0.1.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/LICENSE +30 -0
- package/README.md +31 -2
- package/bootstrap.js +364 -0
- package/dist/index.d.ts +327 -0
- package/dist/index.js +252 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mio contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Third-party components (Flutter/Dart, webview_flutter, webview_flutter_windows,
|
|
26
|
+
window_manager, file_selector, url_launcher, path_provider, @electron/asar,
|
|
27
|
+
resedit, apksigner/zipalign, and the Dart/npm dependencies listed in
|
|
28
|
+
packages/*/THIRD_PARTY_NOTICES.md) keep their own licenses. The prebuilt
|
|
29
|
+
Android/Windows templates in packages/cli/templates embed the Flutter engine;
|
|
30
|
+
review those licenses before redistributing an app built with Mio.
|
package/README.md
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @iyexin/mio-api
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Web 侧 Mio API 与 bootstrap bridge。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @iyexin/mio-api
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Mio, app, fs, clipboard, nativeApi, processApi } from "@iyexin/mio-api";
|
|
11
|
+
|
|
12
|
+
await Mio.ready;
|
|
13
|
+
console.log(await app.info());
|
|
14
|
+
await fs.writeText("notes/hello.txt", "hello");
|
|
15
|
+
await clipboard.writeText("Hello from the shell");
|
|
16
|
+
|
|
17
|
+
// Native library with a small scalar ABI (Android + Windows).
|
|
18
|
+
const lib = await nativeApi.load("demo");
|
|
19
|
+
const sum = await nativeApi.call(lib.handle, "mio_add", "i32(i32,i32)", [2, 3]);
|
|
20
|
+
|
|
21
|
+
// Windows only: start a sidecar and pipe stdio.
|
|
22
|
+
const child = await processApi.spawn({ path: "sidecar/helper.exe" });
|
|
23
|
+
await processApi.write(child.id, "ping\n");
|
|
24
|
+
await processApi.closeStdin(child.id);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- `bootstrap.js` 是零依赖的 classic script,由运行时注入,也可被打包器 import;
|
|
28
|
+
- `index.ts` 是类型封装,所有调用返回 Promise;
|
|
29
|
+
- `window.Mio` 与 `Mio` 共用同一个 bridge;
|
|
30
|
+
- 错误带符号码 `code`(`FS_FORBIDDEN` 等)与数字 `rpcCode`。
|
|
31
|
+
|
|
32
|
+
完整 API 见仓库 `docs/api.md`。
|
package/bootstrap.js
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Mio bootstrap bridge.
|
|
3
|
+
*
|
|
4
|
+
* This file is intentionally dependency-free and runs as a classic script.
|
|
5
|
+
* The runtime injects window.__MIO_BOOT__ before it; dev mode reads the same
|
|
6
|
+
* values from the page query string. It is the only implementation of the
|
|
7
|
+
* WebSocket/JSON-RPC transport.
|
|
8
|
+
*/
|
|
9
|
+
(function () {
|
|
10
|
+
"use strict";
|
|
11
|
+
|
|
12
|
+
if (window.Mio && window.Mio.__mio) return;
|
|
13
|
+
|
|
14
|
+
function readBoot() {
|
|
15
|
+
if (window.__MIO_BOOT__) return window.__MIO_BOOT__;
|
|
16
|
+
try {
|
|
17
|
+
var params = new URLSearchParams(window.location.search);
|
|
18
|
+
var port = params.get("__mio_port");
|
|
19
|
+
var token = params.get("__mio_token");
|
|
20
|
+
if (!port || !token) return null;
|
|
21
|
+
return {
|
|
22
|
+
port: Number(port),
|
|
23
|
+
token: token,
|
|
24
|
+
platform: params.get("__mio_platform") || "web",
|
|
25
|
+
apiVersion: "1.0.0",
|
|
26
|
+
app: {
|
|
27
|
+
id: params.get("__mio_app_id") || "dev.mio.app",
|
|
28
|
+
name: params.get("__mio_app_name") || "Mio App",
|
|
29
|
+
version: params.get("__mio_app_version") || "0.0.0"
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
var boot = readBoot();
|
|
38
|
+
if (!boot || !boot.port || !boot.token) {
|
|
39
|
+
console.error("[Mio] bootstrap data is missing; the bridge was not started");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function MioError(code, message, data) {
|
|
44
|
+
var error = new Error(message);
|
|
45
|
+
error.name = "MioError";
|
|
46
|
+
error.code = code;
|
|
47
|
+
error.data = data;
|
|
48
|
+
return error;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var nextId = 1;
|
|
52
|
+
var pending = new Map();
|
|
53
|
+
var listeners = new Map();
|
|
54
|
+
var outgoing = [];
|
|
55
|
+
var socket = null;
|
|
56
|
+
var reconnectTimer = null;
|
|
57
|
+
var reconnectDelay = 250;
|
|
58
|
+
var closedByApp = false;
|
|
59
|
+
var opened = false;
|
|
60
|
+
var state = "connecting";
|
|
61
|
+
var heartbeat = null;
|
|
62
|
+
var HEARTBEAT_INTERVAL = 5000;
|
|
63
|
+
var HEARTBEAT_TIMEOUT = 4000;
|
|
64
|
+
|
|
65
|
+
function setState(next) {
|
|
66
|
+
if (state === next) return;
|
|
67
|
+
state = next;
|
|
68
|
+
dispatch("bridge.state", { state: next });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var resolveReady;
|
|
72
|
+
var rejectReady;
|
|
73
|
+
var ready = new Promise(function (resolve, reject) {
|
|
74
|
+
resolveReady = resolve;
|
|
75
|
+
rejectReady = reject;
|
|
76
|
+
});
|
|
77
|
+
var readyTimer = setTimeout(function () {
|
|
78
|
+
if (!opened) {
|
|
79
|
+
rejectReady(MioError("MIO_TIMEOUT", "Mio bridge did not connect in time"));
|
|
80
|
+
}
|
|
81
|
+
}, 15000);
|
|
82
|
+
|
|
83
|
+
function endpoint() {
|
|
84
|
+
return (
|
|
85
|
+
"ws://127.0.0.1:" +
|
|
86
|
+
boot.port +
|
|
87
|
+
"/__mio__/rpc?token=" +
|
|
88
|
+
encodeURIComponent(boot.token)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function connect() {
|
|
93
|
+
if (socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
socket = new WebSocket(endpoint());
|
|
97
|
+
|
|
98
|
+
socket.onopen = function () {
|
|
99
|
+
opened = true;
|
|
100
|
+
reconnectDelay = 250;
|
|
101
|
+
clearTimeout(readyTimer);
|
|
102
|
+
setState("open");
|
|
103
|
+
startHeartbeat();
|
|
104
|
+
resolveReady({
|
|
105
|
+
apiVersion: boot.apiVersion || "1.0.0",
|
|
106
|
+
platform: boot.platform || "web",
|
|
107
|
+
app: boot.app || {}
|
|
108
|
+
});
|
|
109
|
+
window.dispatchEvent(new CustomEvent("mio:ready", { detail: boot.app || {} }));
|
|
110
|
+
var queue = outgoing;
|
|
111
|
+
outgoing = [];
|
|
112
|
+
for (var i = 0; i < queue.length; i++) {
|
|
113
|
+
socket.send(queue[i]);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
socket.onmessage = function (event) {
|
|
118
|
+
var message;
|
|
119
|
+
try {
|
|
120
|
+
message = JSON.parse(event.data);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error("[Mio] invalid bridge message", error);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (message.method === "event" && message.params) {
|
|
126
|
+
dispatch(message.params.name, message.params.data);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (message.id === undefined || message.id === null) return;
|
|
130
|
+
var request = pending.get(message.id);
|
|
131
|
+
if (!request) return;
|
|
132
|
+
pending.delete(message.id);
|
|
133
|
+
clearTimeout(request.timer);
|
|
134
|
+
if (message.error) {
|
|
135
|
+
// `mioCode` is the stable symbolic code (FS_FORBIDDEN, ...); the JSON-RPC
|
|
136
|
+
// `code` is an integer and stays available as `rpcCode`.
|
|
137
|
+
var symbol = message.error.mioCode != null ? message.error.mioCode : message.error.code;
|
|
138
|
+
var failure = MioError(
|
|
139
|
+
symbol,
|
|
140
|
+
message.error.message || "Mio call failed",
|
|
141
|
+
message.error.data
|
|
142
|
+
);
|
|
143
|
+
if (typeof message.error.code === "number") {
|
|
144
|
+
failure.rpcCode = message.error.code;
|
|
145
|
+
}
|
|
146
|
+
request.reject(failure);
|
|
147
|
+
} else {
|
|
148
|
+
request.resolve(message.result);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
socket.onerror = function () {
|
|
153
|
+
// onclose will schedule reconnect
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
socket.onclose = function () {
|
|
157
|
+
socket = null;
|
|
158
|
+
stopHeartbeat();
|
|
159
|
+
if (closedByApp) return;
|
|
160
|
+
setState("closed");
|
|
161
|
+
for (var entry of pending.values()) {
|
|
162
|
+
clearTimeout(entry.timer);
|
|
163
|
+
entry.reject(MioError("MIO_DISCONNECTED", "Mio bridge disconnected"));
|
|
164
|
+
}
|
|
165
|
+
pending.clear();
|
|
166
|
+
if (reconnectTimer) return;
|
|
167
|
+
reconnectTimer = setTimeout(function () {
|
|
168
|
+
reconnectTimer = null;
|
|
169
|
+
reconnectDelay = Math.min(reconnectDelay * 2, 10000);
|
|
170
|
+
setState("connecting");
|
|
171
|
+
connect();
|
|
172
|
+
}, reconnectDelay);
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/*
|
|
177
|
+
* A half-open socket looks alive forever: the OS only notices after minutes.
|
|
178
|
+
* A ping every few seconds turns "the shell froze or died" into a fast
|
|
179
|
+
* disconnect instead of a 30 second timeout on the next real call.
|
|
180
|
+
*/
|
|
181
|
+
function startHeartbeat() {
|
|
182
|
+
stopHeartbeat();
|
|
183
|
+
heartbeat = setInterval(function () {
|
|
184
|
+
if (!socket || socket.readyState !== WebSocket.OPEN) return;
|
|
185
|
+
request("ping", {}, HEARTBEAT_TIMEOUT).catch(function () {
|
|
186
|
+
if (!socket) return;
|
|
187
|
+
try {
|
|
188
|
+
socket.close();
|
|
189
|
+
} catch (error) {
|
|
190
|
+
// onclose handles the reconnect.
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}, HEARTBEAT_INTERVAL);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function stopHeartbeat() {
|
|
197
|
+
if (!heartbeat) return;
|
|
198
|
+
clearInterval(heartbeat);
|
|
199
|
+
heartbeat = null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function request(method, params, timeoutMs) {
|
|
203
|
+
return new Promise(function (resolve, reject) {
|
|
204
|
+
if (typeof method !== "string" || method.length === 0) {
|
|
205
|
+
reject(MioError("MIO_BAD_REQUEST", "method must be a non-empty string"));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
var id = nextId++;
|
|
209
|
+
var payload = JSON.stringify({
|
|
210
|
+
jsonrpc: "2.0",
|
|
211
|
+
id: id,
|
|
212
|
+
method: method,
|
|
213
|
+
params: params || {}
|
|
214
|
+
});
|
|
215
|
+
var timer = setTimeout(function () {
|
|
216
|
+
if (!pending.has(id)) return;
|
|
217
|
+
pending.delete(id);
|
|
218
|
+
reject(MioError("MIO_TIMEOUT", "Mio call timed out: " + method));
|
|
219
|
+
}, timeoutMs || 30000);
|
|
220
|
+
pending.set(id, { resolve: resolve, reject: reject, timer: timer });
|
|
221
|
+
|
|
222
|
+
if (socket && socket.readyState === WebSocket.OPEN) {
|
|
223
|
+
socket.send(payload);
|
|
224
|
+
} else {
|
|
225
|
+
outgoing.push(payload);
|
|
226
|
+
connect();
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function invoke(method, params) {
|
|
232
|
+
return request(method, params, 30000);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function blobUrl(path) {
|
|
236
|
+
return (
|
|
237
|
+
"http://127.0.0.1:" +
|
|
238
|
+
boot.port +
|
|
239
|
+
"/__mio__/blob?token=" +
|
|
240
|
+
encodeURIComponent(boot.token) +
|
|
241
|
+
"&path=" +
|
|
242
|
+
encodeURIComponent(path)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function errorFromResponse(response, detail) {
|
|
247
|
+
return MioError("FS_ERROR", detail || "HTTP " + response.status, {
|
|
248
|
+
status: response.status
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function readBlob(path) {
|
|
253
|
+
var response;
|
|
254
|
+
try {
|
|
255
|
+
response = await fetch(blobUrl(path));
|
|
256
|
+
} catch (error) {
|
|
257
|
+
throw MioError("MIO_DISCONNECTED", "Blob request failed: " + path);
|
|
258
|
+
}
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
var body = "";
|
|
261
|
+
try {
|
|
262
|
+
body = await response.text();
|
|
263
|
+
} catch (error) {
|
|
264
|
+
body = "";
|
|
265
|
+
}
|
|
266
|
+
throw errorFromResponse(response, body || undefined);
|
|
267
|
+
}
|
|
268
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async function writeBlob(path, data) {
|
|
272
|
+
var isBytes =
|
|
273
|
+
data instanceof ArrayBuffer ||
|
|
274
|
+
(typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(data));
|
|
275
|
+
if (!isBytes) {
|
|
276
|
+
throw MioError(
|
|
277
|
+
"MIO_BAD_REQUEST",
|
|
278
|
+
"writeBlob expects an ArrayBuffer or typed array"
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
var response;
|
|
282
|
+
try {
|
|
283
|
+
response = await fetch(blobUrl(path), {
|
|
284
|
+
method: "POST",
|
|
285
|
+
headers: { "Content-Type": "application/octet-stream" },
|
|
286
|
+
body: data
|
|
287
|
+
});
|
|
288
|
+
} catch (error) {
|
|
289
|
+
throw MioError("MIO_DISCONNECTED", "Blob request failed: " + path);
|
|
290
|
+
}
|
|
291
|
+
if (!response.ok) {
|
|
292
|
+
var body = "";
|
|
293
|
+
try {
|
|
294
|
+
body = await response.text();
|
|
295
|
+
} catch (error) {
|
|
296
|
+
body = "";
|
|
297
|
+
}
|
|
298
|
+
throw errorFromResponse(response, body || undefined);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function on(name, handler) {
|
|
303
|
+
if (typeof handler !== "function") {
|
|
304
|
+
throw new TypeError("Mio.on requires a handler function");
|
|
305
|
+
}
|
|
306
|
+
var bucket = listeners.get(name);
|
|
307
|
+
if (!bucket) {
|
|
308
|
+
bucket = new Set();
|
|
309
|
+
listeners.set(name, bucket);
|
|
310
|
+
}
|
|
311
|
+
bucket.add(handler);
|
|
312
|
+
return function () {
|
|
313
|
+
bucket.delete(handler);
|
|
314
|
+
if (bucket.size === 0) listeners.delete(name);
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function off(name, handler) {
|
|
319
|
+
var bucket = listeners.get(name);
|
|
320
|
+
if (!bucket) return;
|
|
321
|
+
bucket.delete(handler);
|
|
322
|
+
if (bucket.size === 0) listeners.delete(name);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function once(name, handler) {
|
|
326
|
+
var unsubscribe = on(name, function (data) {
|
|
327
|
+
unsubscribe();
|
|
328
|
+
handler(data);
|
|
329
|
+
});
|
|
330
|
+
return unsubscribe;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function dispatch(name, data) {
|
|
334
|
+
var bucket = listeners.get(name);
|
|
335
|
+
if (!bucket) return;
|
|
336
|
+
for (var handler of Array.from(bucket)) {
|
|
337
|
+
try {
|
|
338
|
+
handler(data);
|
|
339
|
+
} catch (error) {
|
|
340
|
+
console.error("[Mio] event handler failed", name, error);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
window.Mio = {
|
|
346
|
+
__mio: true,
|
|
347
|
+
apiVersion: boot.apiVersion || "1.0.0",
|
|
348
|
+
platform: boot.platform || "web",
|
|
349
|
+
app: boot.app || {},
|
|
350
|
+
ready: ready,
|
|
351
|
+
get state() {
|
|
352
|
+
return state;
|
|
353
|
+
},
|
|
354
|
+
invoke: invoke,
|
|
355
|
+
on: on,
|
|
356
|
+
off: off,
|
|
357
|
+
once: once,
|
|
358
|
+
blobUrl: blobUrl,
|
|
359
|
+
readBlob: readBlob,
|
|
360
|
+
writeBlob: writeBlob
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
connect();
|
|
364
|
+
})();
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import "../bootstrap.js";
|
|
2
|
+
import type { BridgeState, MioBridge } from "./types.js";
|
|
3
|
+
export type { BridgeState, MioBridge, MioBootstrap, } from "./types.js";
|
|
4
|
+
export interface AppFeatures {
|
|
5
|
+
/** `nativeApi` is usable: supported platform and a packaged build. */
|
|
6
|
+
native: boolean;
|
|
7
|
+
/** `processApi` is usable (Windows only). */
|
|
8
|
+
process: boolean;
|
|
9
|
+
/** Window controls are available. */
|
|
10
|
+
window: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface AppInfo {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
title: string;
|
|
17
|
+
platform: string;
|
|
18
|
+
apiVersion: string;
|
|
19
|
+
templateVersion: string;
|
|
20
|
+
/** True when the page is served by a dev server instead of the app archive. */
|
|
21
|
+
dev: boolean;
|
|
22
|
+
/** ISO timestamp of when the shell started. */
|
|
23
|
+
startedAt: string;
|
|
24
|
+
/** Milliseconds since the shell started. */
|
|
25
|
+
uptimeMs: number;
|
|
26
|
+
features: AppFeatures;
|
|
27
|
+
}
|
|
28
|
+
export interface PlatformInfo {
|
|
29
|
+
os: string;
|
|
30
|
+
osVersion: string;
|
|
31
|
+
locale: string;
|
|
32
|
+
processors: number;
|
|
33
|
+
platform: string;
|
|
34
|
+
/** ABI this shell runs as: `arm64`, `x64`, `arm`, `x86`. */
|
|
35
|
+
abi: string;
|
|
36
|
+
}
|
|
37
|
+
export interface AppPaths {
|
|
38
|
+
/** Root of everything the app owns. */
|
|
39
|
+
data: string;
|
|
40
|
+
/** The only writable sandbox; paths passed to `fs.*` are relative to it. */
|
|
41
|
+
app: string;
|
|
42
|
+
/** Where native libraries are extracted. */
|
|
43
|
+
native: string;
|
|
44
|
+
/** Directory of the installed executable. */
|
|
45
|
+
install: string;
|
|
46
|
+
/** System temp directory. */
|
|
47
|
+
temp: string;
|
|
48
|
+
}
|
|
49
|
+
export interface AppLogResult {
|
|
50
|
+
/** Path of the log file, relative to the `fs` sandbox. */
|
|
51
|
+
path: string;
|
|
52
|
+
}
|
|
53
|
+
export interface FileEntry {
|
|
54
|
+
name: string;
|
|
55
|
+
path: string;
|
|
56
|
+
type: string;
|
|
57
|
+
size: number;
|
|
58
|
+
modified: string;
|
|
59
|
+
}
|
|
60
|
+
export interface FileStat {
|
|
61
|
+
type: string;
|
|
62
|
+
size: number;
|
|
63
|
+
modified: string;
|
|
64
|
+
}
|
|
65
|
+
export interface WindowState {
|
|
66
|
+
supported: boolean;
|
|
67
|
+
width?: number;
|
|
68
|
+
height?: number;
|
|
69
|
+
isMaximized?: boolean;
|
|
70
|
+
isFullScreen?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface ProcessSpawnOptions {
|
|
73
|
+
/**
|
|
74
|
+
* Executable path. Relative paths are resolved against the install directory
|
|
75
|
+
* (next to the app executable) and then the app data directory; absolute
|
|
76
|
+
* paths must resolve inside one of those two roots.
|
|
77
|
+
*/
|
|
78
|
+
path: string;
|
|
79
|
+
args?: string[];
|
|
80
|
+
cwd?: string;
|
|
81
|
+
env?: Record<string, string>;
|
|
82
|
+
}
|
|
83
|
+
export interface ProcessInfo {
|
|
84
|
+
id: string;
|
|
85
|
+
pid: number;
|
|
86
|
+
executable: string;
|
|
87
|
+
cwd?: string;
|
|
88
|
+
}
|
|
89
|
+
export interface ProcessChunk {
|
|
90
|
+
id: string;
|
|
91
|
+
pid: number;
|
|
92
|
+
bytes: Uint8Array;
|
|
93
|
+
}
|
|
94
|
+
export interface ProcessExitEvent {
|
|
95
|
+
id: string;
|
|
96
|
+
pid: number;
|
|
97
|
+
code: number;
|
|
98
|
+
signal: string | null;
|
|
99
|
+
executable?: string;
|
|
100
|
+
}
|
|
101
|
+
export interface NativeHandle {
|
|
102
|
+
handle: string;
|
|
103
|
+
name: string;
|
|
104
|
+
/** ABI the library was checked against, e.g. `arm64` or `x64`. */
|
|
105
|
+
abi: string;
|
|
106
|
+
/** Path inside the app archive, e.g. `native/arm64/demo.so`. */
|
|
107
|
+
path: string;
|
|
108
|
+
/** Absolute path of the extracted copy the loader opened. */
|
|
109
|
+
file: string;
|
|
110
|
+
/** Whether the library exports the optional `mio_start` entry point. */
|
|
111
|
+
entry: boolean;
|
|
112
|
+
started: boolean;
|
|
113
|
+
}
|
|
114
|
+
export interface NativeStartResult {
|
|
115
|
+
handle: string;
|
|
116
|
+
/** Value returned by `mio_start`; null when the entry is still running. */
|
|
117
|
+
code: number | null;
|
|
118
|
+
running: boolean;
|
|
119
|
+
}
|
|
120
|
+
export interface NativeStopResult {
|
|
121
|
+
handle: string;
|
|
122
|
+
/** True when `mio_stop` existed and returned. */
|
|
123
|
+
stopped: boolean;
|
|
124
|
+
/** `not started`, `no mio_stop`, or the error the export raised. */
|
|
125
|
+
reason?: string;
|
|
126
|
+
/** The export did not return within the shutdown budget. */
|
|
127
|
+
timedOut?: boolean;
|
|
128
|
+
}
|
|
129
|
+
export interface NativeEvent {
|
|
130
|
+
handle: string;
|
|
131
|
+
/** Caller-chosen id passed to the sink by native code. */
|
|
132
|
+
event: number;
|
|
133
|
+
a: number;
|
|
134
|
+
b: number;
|
|
135
|
+
c: number;
|
|
136
|
+
}
|
|
137
|
+
export type NativeValue = number | string;
|
|
138
|
+
export declare function getMio(): Promise<MioBridge>;
|
|
139
|
+
/**
|
|
140
|
+
* Native libraries with a small, fixed scalar ABI.
|
|
141
|
+
*
|
|
142
|
+
* A library is packed under `native/<abi>/<name>.so|dll` in the app content,
|
|
143
|
+
* extracted to the app data directory on first load, and opened with `dlopen` /
|
|
144
|
+
* `LoadLibrary`. Two ways to use it:
|
|
145
|
+
*
|
|
146
|
+
* - `call` invokes exported functions with the supported scalar signatures
|
|
147
|
+
* (`i32`, `i64`, `f64`, `str` arguments; `void`, `i32`, `i64`, `f64` returns);
|
|
148
|
+
* - `start` calls the optional `mio_start(sink, config)` entry, after which the
|
|
149
|
+
* library can push scalar events to the page through the sink.
|
|
150
|
+
*
|
|
151
|
+
* Anything beyond scalars — buffers, structs, callbacks with pointers — is out
|
|
152
|
+
* of scope by design: use files, the blob endpoint, or a sidecar process.
|
|
153
|
+
*/
|
|
154
|
+
export declare const nativeApi: {
|
|
155
|
+
/** Loads `native/<abi>/<name>.<ext>` from the app content. */
|
|
156
|
+
load: (name: string) => Promise<NativeHandle>;
|
|
157
|
+
/** Calls `mio_start(sink, config)`; returns its result or reports it running. */
|
|
158
|
+
start: (handle: string, config?: string) => Promise<NativeStartResult>;
|
|
159
|
+
/**
|
|
160
|
+
* Calls the optional `mio_stop()` export and marks the library as stopped.
|
|
161
|
+
* The library stays loaded; `start` can be called again afterwards.
|
|
162
|
+
*/
|
|
163
|
+
stop: (handle: string) => Promise<NativeStopResult>;
|
|
164
|
+
/**
|
|
165
|
+
* Calls an exported function. `signature` must be one of the supported
|
|
166
|
+
* shapes, e.g. `i32(i32,i32)`, `f64(str)`, `void()`.
|
|
167
|
+
*/
|
|
168
|
+
call: (handle: string, symbol: string, signature: string, args?: NativeValue[]) => Promise<number | null>;
|
|
169
|
+
/**
|
|
170
|
+
* Pushes a scalar event into the library through its optional `mio_event`
|
|
171
|
+
* export — the reverse direction of `onEvent`:
|
|
172
|
+
*
|
|
173
|
+
* ```c
|
|
174
|
+
* void mio_event(int32_t event, int64_t a, int64_t b, double c);
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
emit: (handle: string, event: number, a?: number, b?: number, c?: number) => Promise<void>;
|
|
178
|
+
list: () => Promise<NativeHandle[]>;
|
|
179
|
+
/** Scalar events pushed by native code through the `mio_start` sink. */
|
|
180
|
+
onEvent: (handler: (event: NativeEvent) => void) => Promise<() => void>;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* Sidecar processes. Windows only; every other platform rejects with
|
|
184
|
+
* `UNSUPPORTED`.
|
|
185
|
+
*
|
|
186
|
+
* Mio does not provide native plugins. This namespace only starts a process and
|
|
187
|
+
* moves its stdio; the wire protocol between the app and the sidecar is the
|
|
188
|
+
* app's own business. Named `processApi` rather than `process` so importing it
|
|
189
|
+
* never shadows the global `process`.
|
|
190
|
+
*/
|
|
191
|
+
export declare const processApi: {
|
|
192
|
+
spawn: (options: ProcessSpawnOptions) => Promise<ProcessInfo>;
|
|
193
|
+
/** Sends bytes to the child's stdin. Strings are encoded as UTF-8. */
|
|
194
|
+
write: (id: string, data: Uint8Array | ArrayBuffer | string) => Promise<void>;
|
|
195
|
+
closeStdin: (id: string) => Promise<void>;
|
|
196
|
+
/** SIGTERM, escalating to SIGKILL after five seconds. */
|
|
197
|
+
kill: (id: string, signal?: "term" | "kill") => Promise<{
|
|
198
|
+
id: string;
|
|
199
|
+
pid: number;
|
|
200
|
+
killed: boolean;
|
|
201
|
+
}>;
|
|
202
|
+
list: () => Promise<ProcessInfo[]>;
|
|
203
|
+
/** stdout chunks; concatenate `bytes` — chunk boundaries are arbitrary. */
|
|
204
|
+
onStdout: (handler: (chunk: ProcessChunk) => void) => Promise<() => void>;
|
|
205
|
+
onStderr: (handler: (chunk: ProcessChunk) => void) => Promise<() => void>;
|
|
206
|
+
onExit: (handler: (event: ProcessExitEvent) => void) => Promise<() => void>;
|
|
207
|
+
};
|
|
208
|
+
export declare const Mio: {
|
|
209
|
+
readonly ready: Promise<{
|
|
210
|
+
apiVersion: string;
|
|
211
|
+
platform: string;
|
|
212
|
+
app: Record<string, unknown>;
|
|
213
|
+
}>;
|
|
214
|
+
/** `connecting` | `open` | `closed`; changes arrive as `bridge.state`. */
|
|
215
|
+
connectionState(): Promise<BridgeState>;
|
|
216
|
+
invoke<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
|
|
217
|
+
on(name: string, handler: (data: unknown) => void): Promise<() => void>;
|
|
218
|
+
off(name: string, handler: (data: unknown) => void): Promise<void>;
|
|
219
|
+
once(name: string, handler: (data: unknown) => void): Promise<() => void>;
|
|
220
|
+
process: {
|
|
221
|
+
spawn: (options: ProcessSpawnOptions) => Promise<ProcessInfo>;
|
|
222
|
+
/** Sends bytes to the child's stdin. Strings are encoded as UTF-8. */
|
|
223
|
+
write: (id: string, data: Uint8Array | ArrayBuffer | string) => Promise<void>;
|
|
224
|
+
closeStdin: (id: string) => Promise<void>;
|
|
225
|
+
/** SIGTERM, escalating to SIGKILL after five seconds. */
|
|
226
|
+
kill: (id: string, signal?: "term" | "kill") => Promise<{
|
|
227
|
+
id: string;
|
|
228
|
+
pid: number;
|
|
229
|
+
killed: boolean;
|
|
230
|
+
}>;
|
|
231
|
+
list: () => Promise<ProcessInfo[]>;
|
|
232
|
+
/** stdout chunks; concatenate `bytes` — chunk boundaries are arbitrary. */
|
|
233
|
+
onStdout: (handler: (chunk: ProcessChunk) => void) => Promise<() => void>;
|
|
234
|
+
onStderr: (handler: (chunk: ProcessChunk) => void) => Promise<() => void>;
|
|
235
|
+
onExit: (handler: (event: ProcessExitEvent) => void) => Promise<() => void>;
|
|
236
|
+
};
|
|
237
|
+
native: {
|
|
238
|
+
/** Loads `native/<abi>/<name>.<ext>` from the app content. */
|
|
239
|
+
load: (name: string) => Promise<NativeHandle>;
|
|
240
|
+
/** Calls `mio_start(sink, config)`; returns its result or reports it running. */
|
|
241
|
+
start: (handle: string, config?: string) => Promise<NativeStartResult>;
|
|
242
|
+
/**
|
|
243
|
+
* Calls the optional `mio_stop()` export and marks the library as stopped.
|
|
244
|
+
* The library stays loaded; `start` can be called again afterwards.
|
|
245
|
+
*/
|
|
246
|
+
stop: (handle: string) => Promise<NativeStopResult>;
|
|
247
|
+
/**
|
|
248
|
+
* Calls an exported function. `signature` must be one of the supported
|
|
249
|
+
* shapes, e.g. `i32(i32,i32)`, `f64(str)`, `void()`.
|
|
250
|
+
*/
|
|
251
|
+
call: (handle: string, symbol: string, signature: string, args?: NativeValue[]) => Promise<number | null>;
|
|
252
|
+
/**
|
|
253
|
+
* Pushes a scalar event into the library through its optional `mio_event`
|
|
254
|
+
* export — the reverse direction of `onEvent`:
|
|
255
|
+
*
|
|
256
|
+
* ```c
|
|
257
|
+
* void mio_event(int32_t event, int64_t a, int64_t b, double c);
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
emit: (handle: string, event: number, a?: number, b?: number, c?: number) => Promise<void>;
|
|
261
|
+
list: () => Promise<NativeHandle[]>;
|
|
262
|
+
/** Scalar events pushed by native code through the `mio_start` sink. */
|
|
263
|
+
onEvent: (handler: (event: NativeEvent) => void) => Promise<() => void>;
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
export declare const app: {
|
|
267
|
+
info: () => Promise<AppInfo>;
|
|
268
|
+
/** Absolute directories the app owns; `app` is the writable sandbox. */
|
|
269
|
+
paths: () => Promise<AppPaths>;
|
|
270
|
+
/**
|
|
271
|
+
* Appends a timestamped `level message` line to `logs/mio.log` (rotated at
|
|
272
|
+
* ~1 MB). Android has no console, so the file is the useful sink.
|
|
273
|
+
*/
|
|
274
|
+
log: (level: "debug" | "info" | "warn" | "error", message: string) => Promise<AppLogResult>;
|
|
275
|
+
quit: () => Promise<void>;
|
|
276
|
+
};
|
|
277
|
+
export declare const platform: {
|
|
278
|
+
info: () => Promise<PlatformInfo>;
|
|
279
|
+
};
|
|
280
|
+
export declare const fs: {
|
|
281
|
+
readText: (path: string) => Promise<string>;
|
|
282
|
+
writeText: (path: string, text: string) => Promise<void>;
|
|
283
|
+
appendText: (path: string, text: string) => Promise<void>;
|
|
284
|
+
readBytes: (path: string) => Promise<Uint8Array>;
|
|
285
|
+
writeBytes: (path: string, data: Uint8Array | ArrayBuffer) => Promise<void>;
|
|
286
|
+
list: (path?: string) => Promise<FileEntry[]>;
|
|
287
|
+
stat: (path: string) => Promise<FileStat | null>;
|
|
288
|
+
mkdir: (path: string) => Promise<void>;
|
|
289
|
+
remove: (path: string, recursive?: boolean) => Promise<boolean>;
|
|
290
|
+
rename: (from: string, to: string) => Promise<void>;
|
|
291
|
+
exists: (path: string) => Promise<boolean>;
|
|
292
|
+
/** URL usable with fetch() for streaming reads (Range supported). */
|
|
293
|
+
blobUrl: (path: string) => Promise<string>;
|
|
294
|
+
};
|
|
295
|
+
export declare const dialog: {
|
|
296
|
+
openFile: (extensions?: string[]) => Promise<string | null>;
|
|
297
|
+
openDirectory: () => Promise<string | null>;
|
|
298
|
+
saveFile: (suggestedName?: string) => Promise<string | null>;
|
|
299
|
+
};
|
|
300
|
+
export declare const clipboard: {
|
|
301
|
+
readText: () => Promise<string | null>;
|
|
302
|
+
writeText: (text: string) => Promise<void>;
|
|
303
|
+
};
|
|
304
|
+
export declare const shell: {
|
|
305
|
+
openExternal: (url: string) => Promise<void>;
|
|
306
|
+
/**
|
|
307
|
+
* Opens a file from the app sandbox with the system default application.
|
|
308
|
+
* Windows only: Android would need a content provider Mio does not ship.
|
|
309
|
+
*/
|
|
310
|
+
openPath: (path: string) => Promise<void>;
|
|
311
|
+
/** Shows a sandbox file or folder in Explorer, selected when possible. */
|
|
312
|
+
reveal: (path: string) => Promise<void>;
|
|
313
|
+
};
|
|
314
|
+
export declare const windowApi: {
|
|
315
|
+
state: () => Promise<WindowState>;
|
|
316
|
+
setTitle: (title: string) => Promise<void>;
|
|
317
|
+
minimize: () => Promise<void>;
|
|
318
|
+
maximize: () => Promise<void>;
|
|
319
|
+
restore: () => Promise<void>;
|
|
320
|
+
close: () => Promise<void>;
|
|
321
|
+
center: () => Promise<void>;
|
|
322
|
+
moveTo: (x: number, y: number) => Promise<void>;
|
|
323
|
+
setSize: (width: number, height: number) => Promise<void>;
|
|
324
|
+
setFullScreen: (fullScreen: boolean) => Promise<void>;
|
|
325
|
+
setAlwaysOnTop: (alwaysOnTop: boolean) => Promise<void>;
|
|
326
|
+
};
|
|
327
|
+
export default Mio;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// Side-effect import: installs window.Mio before app code runs. In production
|
|
2
|
+
// the runtime also injects this file before the app bundle; the bootstrap
|
|
3
|
+
// guards against double installation.
|
|
4
|
+
import "../bootstrap.js";
|
|
5
|
+
function toBase64(data) {
|
|
6
|
+
let bytes;
|
|
7
|
+
if (typeof data === "string") {
|
|
8
|
+
bytes = new TextEncoder().encode(data);
|
|
9
|
+
}
|
|
10
|
+
else if (data instanceof ArrayBuffer) {
|
|
11
|
+
bytes = new Uint8Array(data);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
15
|
+
}
|
|
16
|
+
let binary = "";
|
|
17
|
+
for (let offset = 0; offset < bytes.length; offset += 0x8000) {
|
|
18
|
+
binary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));
|
|
19
|
+
}
|
|
20
|
+
return btoa(binary);
|
|
21
|
+
}
|
|
22
|
+
function fromBase64(data) {
|
|
23
|
+
const binary = atob(data);
|
|
24
|
+
const bytes = new Uint8Array(binary.length);
|
|
25
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
26
|
+
bytes[index] = binary.charCodeAt(index);
|
|
27
|
+
}
|
|
28
|
+
return bytes;
|
|
29
|
+
}
|
|
30
|
+
function waitForBridge(timeoutMs = 10_000) {
|
|
31
|
+
if (typeof window === "undefined") {
|
|
32
|
+
return Promise.reject(new Error("Mio API is only available in a browser"));
|
|
33
|
+
}
|
|
34
|
+
if (window.Mio)
|
|
35
|
+
return Promise.resolve(window.Mio);
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const started = Date.now();
|
|
38
|
+
const timer = window.setInterval(() => {
|
|
39
|
+
if (window.Mio) {
|
|
40
|
+
window.clearInterval(timer);
|
|
41
|
+
resolve(window.Mio);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (Date.now() - started > timeoutMs) {
|
|
45
|
+
window.clearInterval(timer);
|
|
46
|
+
reject(new Error("Mio bridge did not become ready"));
|
|
47
|
+
}
|
|
48
|
+
}, 50);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function injectBootstrapFromQuery() {
|
|
52
|
+
if (typeof document === "undefined")
|
|
53
|
+
return false;
|
|
54
|
+
const params = new URLSearchParams(window.location.search);
|
|
55
|
+
const port = params.get("__mio_port");
|
|
56
|
+
if (!port)
|
|
57
|
+
return false;
|
|
58
|
+
if (document.querySelector("script[data-mio-bootstrap]"))
|
|
59
|
+
return true;
|
|
60
|
+
await new Promise((resolve, reject) => {
|
|
61
|
+
const script = document.createElement("script");
|
|
62
|
+
script.src = `http://127.0.0.1:${port}/__mio__/bootstrap.js`;
|
|
63
|
+
script.async = true;
|
|
64
|
+
script.dataset.mioBootstrap = "true";
|
|
65
|
+
script.onload = () => resolve();
|
|
66
|
+
script.onerror = () => reject(new Error("Failed to load the Mio bootstrap"));
|
|
67
|
+
document.head.appendChild(script);
|
|
68
|
+
});
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
export async function getMio() {
|
|
72
|
+
if (typeof window === "undefined") {
|
|
73
|
+
throw new Error("Mio API is only available in a browser");
|
|
74
|
+
}
|
|
75
|
+
if (window.Mio)
|
|
76
|
+
return window.Mio;
|
|
77
|
+
// Dev mode: the shell adds __mio_port/__mio_token to the Vite URL. The
|
|
78
|
+
// bootstrap file may also be bundled by the app, in which case this is a
|
|
79
|
+
// no-op. Either way window.Mio is installed exactly once.
|
|
80
|
+
if (!window.Mio) {
|
|
81
|
+
try {
|
|
82
|
+
await injectBootstrapFromQuery();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Fall through to waitForBridge for a useful timeout.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return await waitForBridge();
|
|
89
|
+
}
|
|
90
|
+
async function invoke(method, params) {
|
|
91
|
+
const bridge = await getMio();
|
|
92
|
+
return await bridge.invoke(method, params);
|
|
93
|
+
}
|
|
94
|
+
async function subscribeProcessStream(name, handler) {
|
|
95
|
+
return await Mio.on(name, (data) => {
|
|
96
|
+
const event = data;
|
|
97
|
+
handler({ id: event.id, pid: event.pid, bytes: fromBase64(event.data) });
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Native libraries with a small, fixed scalar ABI.
|
|
102
|
+
*
|
|
103
|
+
* A library is packed under `native/<abi>/<name>.so|dll` in the app content,
|
|
104
|
+
* extracted to the app data directory on first load, and opened with `dlopen` /
|
|
105
|
+
* `LoadLibrary`. Two ways to use it:
|
|
106
|
+
*
|
|
107
|
+
* - `call` invokes exported functions with the supported scalar signatures
|
|
108
|
+
* (`i32`, `i64`, `f64`, `str` arguments; `void`, `i32`, `i64`, `f64` returns);
|
|
109
|
+
* - `start` calls the optional `mio_start(sink, config)` entry, after which the
|
|
110
|
+
* library can push scalar events to the page through the sink.
|
|
111
|
+
*
|
|
112
|
+
* Anything beyond scalars — buffers, structs, callbacks with pointers — is out
|
|
113
|
+
* of scope by design: use files, the blob endpoint, or a sidecar process.
|
|
114
|
+
*/
|
|
115
|
+
export const nativeApi = {
|
|
116
|
+
/** Loads `native/<abi>/<name>.<ext>` from the app content. */
|
|
117
|
+
load: (name) => invoke("native.load", { name }),
|
|
118
|
+
/** Calls `mio_start(sink, config)`; returns its result or reports it running. */
|
|
119
|
+
start: (handle, config) => invoke("native.start", { handle, config }),
|
|
120
|
+
/**
|
|
121
|
+
* Calls the optional `mio_stop()` export and marks the library as stopped.
|
|
122
|
+
* The library stays loaded; `start` can be called again afterwards.
|
|
123
|
+
*/
|
|
124
|
+
stop: (handle) => invoke("native.stop", { handle }),
|
|
125
|
+
/**
|
|
126
|
+
* Calls an exported function. `signature` must be one of the supported
|
|
127
|
+
* shapes, e.g. `i32(i32,i32)`, `f64(str)`, `void()`.
|
|
128
|
+
*/
|
|
129
|
+
call: (handle, symbol, signature, args = []) => invoke("native.call", { handle, symbol, signature, args }),
|
|
130
|
+
/**
|
|
131
|
+
* Pushes a scalar event into the library through its optional `mio_event`
|
|
132
|
+
* export — the reverse direction of `onEvent`:
|
|
133
|
+
*
|
|
134
|
+
* ```c
|
|
135
|
+
* void mio_event(int32_t event, int64_t a, int64_t b, double c);
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
emit: (handle, event, a = 0, b = 0, c = 0) => invoke("native.emit", { handle, event, a, b, c }),
|
|
139
|
+
list: () => invoke("native.list"),
|
|
140
|
+
/** Scalar events pushed by native code through the `mio_start` sink. */
|
|
141
|
+
onEvent: (handler) => Mio.on("native.event", (data) => handler(data)),
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Sidecar processes. Windows only; every other platform rejects with
|
|
145
|
+
* `UNSUPPORTED`.
|
|
146
|
+
*
|
|
147
|
+
* Mio does not provide native plugins. This namespace only starts a process and
|
|
148
|
+
* moves its stdio; the wire protocol between the app and the sidecar is the
|
|
149
|
+
* app's own business. Named `processApi` rather than `process` so importing it
|
|
150
|
+
* never shadows the global `process`.
|
|
151
|
+
*/
|
|
152
|
+
export const processApi = {
|
|
153
|
+
spawn: (options) => invoke("process.spawn", { ...options }),
|
|
154
|
+
/** Sends bytes to the child's stdin. Strings are encoded as UTF-8. */
|
|
155
|
+
write: (id, data) => invoke("process.write", { id, data: toBase64(data) }),
|
|
156
|
+
closeStdin: (id) => invoke("process.closeStdin", { id }),
|
|
157
|
+
/** SIGTERM, escalating to SIGKILL after five seconds. */
|
|
158
|
+
kill: (id, signal = "term") => invoke("process.kill", { id, signal }),
|
|
159
|
+
list: () => invoke("process.list"),
|
|
160
|
+
/** stdout chunks; concatenate `bytes` — chunk boundaries are arbitrary. */
|
|
161
|
+
onStdout: (handler) => subscribeProcessStream("process.stdout", handler),
|
|
162
|
+
onStderr: (handler) => subscribeProcessStream("process.stderr", handler),
|
|
163
|
+
onExit: (handler) => Mio.on("process.exit", (data) => handler(data)),
|
|
164
|
+
};
|
|
165
|
+
export const Mio = {
|
|
166
|
+
get ready() {
|
|
167
|
+
return getMio().then((bridge) => bridge.ready);
|
|
168
|
+
},
|
|
169
|
+
/** `connecting` | `open` | `closed`; changes arrive as `bridge.state`. */
|
|
170
|
+
async connectionState() {
|
|
171
|
+
return (await getMio()).state;
|
|
172
|
+
},
|
|
173
|
+
async invoke(method, params) {
|
|
174
|
+
return await invoke(method, params);
|
|
175
|
+
},
|
|
176
|
+
async on(name, handler) {
|
|
177
|
+
return (await getMio()).on(name, handler);
|
|
178
|
+
},
|
|
179
|
+
async off(name, handler) {
|
|
180
|
+
(await getMio()).off(name, handler);
|
|
181
|
+
},
|
|
182
|
+
async once(name, handler) {
|
|
183
|
+
return (await getMio()).once(name, handler);
|
|
184
|
+
},
|
|
185
|
+
process: processApi,
|
|
186
|
+
native: nativeApi,
|
|
187
|
+
};
|
|
188
|
+
export const app = {
|
|
189
|
+
info: () => invoke("app.info"),
|
|
190
|
+
/** Absolute directories the app owns; `app` is the writable sandbox. */
|
|
191
|
+
paths: () => invoke("app.paths"),
|
|
192
|
+
/**
|
|
193
|
+
* Appends a timestamped `level message` line to `logs/mio.log` (rotated at
|
|
194
|
+
* ~1 MB). Android has no console, so the file is the useful sink.
|
|
195
|
+
*/
|
|
196
|
+
log: (level, message) => invoke("app.log", { level, message }),
|
|
197
|
+
quit: () => invoke("app.quit"),
|
|
198
|
+
};
|
|
199
|
+
export const platform = {
|
|
200
|
+
info: () => invoke("platform.info"),
|
|
201
|
+
};
|
|
202
|
+
export const fs = {
|
|
203
|
+
readText: (path) => invoke("fs.readText", { path }),
|
|
204
|
+
writeText: (path, text) => invoke("fs.writeText", { path, text }),
|
|
205
|
+
appendText: (path, text) => invoke("fs.appendText", { path, text }),
|
|
206
|
+
// Binary reads and writes go through the HTTP blob endpoint: they stream and
|
|
207
|
+
// avoid the base64 round trip that the JSON methods need.
|
|
208
|
+
readBytes: async (path) => (await getMio()).readBlob(path),
|
|
209
|
+
writeBytes: async (path, data) => await (await getMio()).writeBlob(path, data),
|
|
210
|
+
list: (path = ".") => invoke("fs.list", { path }),
|
|
211
|
+
stat: (path) => invoke("fs.stat", { path }),
|
|
212
|
+
mkdir: (path) => invoke("fs.mkdir", { path }),
|
|
213
|
+
remove: (path, recursive = false) => invoke("fs.remove", { path, recursive }),
|
|
214
|
+
rename: (from, to) => invoke("fs.rename", { from, to }),
|
|
215
|
+
exists: (path) => invoke("fs.exists", { path }),
|
|
216
|
+
/** URL usable with fetch() for streaming reads (Range supported). */
|
|
217
|
+
blobUrl: async (path) => (await getMio()).blobUrl(path),
|
|
218
|
+
};
|
|
219
|
+
export const dialog = {
|
|
220
|
+
openFile: (extensions) => invoke("dialog.openFile", { extensions }),
|
|
221
|
+
openDirectory: () => invoke("dialog.openDirectory"),
|
|
222
|
+
saveFile: (suggestedName) => invoke("dialog.saveFile", { suggestedName }),
|
|
223
|
+
};
|
|
224
|
+
export const clipboard = {
|
|
225
|
+
readText: () => invoke("clipboard.readText"),
|
|
226
|
+
writeText: (text) => invoke("clipboard.writeText", { text }),
|
|
227
|
+
};
|
|
228
|
+
export const shell = {
|
|
229
|
+
openExternal: (url) => invoke("shell.openExternal", { url }),
|
|
230
|
+
/**
|
|
231
|
+
* Opens a file from the app sandbox with the system default application.
|
|
232
|
+
* Windows only: Android would need a content provider Mio does not ship.
|
|
233
|
+
*/
|
|
234
|
+
openPath: (path) => invoke("shell.openPath", { path }),
|
|
235
|
+
/** Shows a sandbox file or folder in Explorer, selected when possible. */
|
|
236
|
+
reveal: (path) => invoke("shell.reveal", { path }),
|
|
237
|
+
};
|
|
238
|
+
export const windowApi = {
|
|
239
|
+
state: () => invoke("window.state"),
|
|
240
|
+
setTitle: (title) => invoke("window.setTitle", { title }),
|
|
241
|
+
minimize: () => invoke("window.minimize"),
|
|
242
|
+
maximize: () => invoke("window.maximize"),
|
|
243
|
+
restore: () => invoke("window.restore"),
|
|
244
|
+
close: () => invoke("window.close"),
|
|
245
|
+
center: () => invoke("window.center"),
|
|
246
|
+
moveTo: (x, y) => invoke("window.moveTo", { x, y }),
|
|
247
|
+
setSize: (width, height) => invoke("window.setSize", { width, height }),
|
|
248
|
+
setFullScreen: (fullScreen) => invoke("window.setFullScreen", { fullScreen }),
|
|
249
|
+
setAlwaysOnTop: (alwaysOnTop) => invoke("window.setAlwaysOnTop", { alwaysOnTop }),
|
|
250
|
+
};
|
|
251
|
+
export default Mio;
|
|
252
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface MioBootstrap {
|
|
2
|
+
port: number;
|
|
3
|
+
token: string;
|
|
4
|
+
apiVersion: string;
|
|
5
|
+
platform: string;
|
|
6
|
+
app: {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export type BridgeState = "connecting" | "open" | "closed";
|
|
13
|
+
export interface MioBridge {
|
|
14
|
+
readonly __mio: true;
|
|
15
|
+
readonly apiVersion: string;
|
|
16
|
+
readonly platform: string;
|
|
17
|
+
readonly app: {
|
|
18
|
+
id?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
version?: string;
|
|
21
|
+
};
|
|
22
|
+
readonly ready: Promise<{
|
|
23
|
+
apiVersion: string;
|
|
24
|
+
platform: string;
|
|
25
|
+
app: Record<string, unknown>;
|
|
26
|
+
}>;
|
|
27
|
+
/** Transport state; changes are reported as the `bridge.state` event. */
|
|
28
|
+
readonly state: BridgeState;
|
|
29
|
+
invoke<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
|
|
30
|
+
on(name: string, handler: (data: unknown) => void): () => void;
|
|
31
|
+
off(name: string, handler: (data: unknown) => void): void;
|
|
32
|
+
once(name: string, handler: (data: unknown) => void): () => void;
|
|
33
|
+
/** Absolute URL of the blob endpoint for a file, usable with fetch(). */
|
|
34
|
+
blobUrl(path: string): string;
|
|
35
|
+
/** Read a file over HTTP (streaming, no base64 overhead). */
|
|
36
|
+
readBlob(path: string): Promise<Uint8Array>;
|
|
37
|
+
/** Write a file over HTTP. */
|
|
38
|
+
writeBlob(path: string, data: ArrayBuffer | ArrayBufferView): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
declare global {
|
|
41
|
+
interface Window {
|
|
42
|
+
Mio?: MioBridge;
|
|
43
|
+
__MIO_BOOT__?: MioBootstrap;
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyexin/mio-api",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Typed Mio bridge API for web applications",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./bootstrap": "./bootstrap.js",
|
|
13
|
+
"./bootstrap.js": "./bootstrap.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"bootstrap.js"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=20"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/iYeXin/Mio.git",
|
|
26
|
+
"directory": "packages/api"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/iYeXin/Mio#readme",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/iYeXin/Mio/issues"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"mio",
|
|
34
|
+
"flutter",
|
|
35
|
+
"webview",
|
|
36
|
+
"web-app",
|
|
37
|
+
"android",
|
|
38
|
+
"windows"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc -p tsconfig.json",
|
|
45
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
46
|
+
"test": "node --test"
|
|
47
|
+
}
|
|
6
48
|
}
|