bunite-core 0.0.11 → 0.0.13
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/package.json +1 -1
- package/src/bun/core/BrowserView.ts +5 -2
- package/src/shared/rpc.ts +6 -4
- package/src/shared/webRpcHandler.ts +76 -32
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { ptr } from "bun:ffi";
|
|
|
2
2
|
import { buildViewPreloadScript } from "../preload/inline";
|
|
3
3
|
import { log } from "../../shared/log";
|
|
4
4
|
import { buniteEventEmitter } from "../events/eventEmitter";
|
|
5
|
-
import { defineBuniteRPC, type BuniteRPCConfig, type BuniteRPCSchema, type RPCWithTransport
|
|
5
|
+
import { defineBuniteRPC, type BuniteRPCConfig, type BuniteRPCSchema, type RPCWithTransport } from "../../shared/rpc";
|
|
6
6
|
import { createWebRPCHandler } from "../../shared/webRpcHandler";
|
|
7
7
|
import { ensureNativeRuntime, getNativeLibrary, toCString, waitForViewReady, cancelWaitForViewReady } from "../proc/native";
|
|
8
8
|
import { attachBrowserViewRegistry, getRPCPort, sendMessageToView } from "./Socket";
|
|
@@ -165,8 +165,11 @@ export class BrowserView<T extends RPCWithTransport = RPCWithTransport> {
|
|
|
165
165
|
config: BuniteRPCConfig<Schema, "bun">
|
|
166
166
|
) {
|
|
167
167
|
const rpc = defineBuniteRPC("bun", config);
|
|
168
|
+
const webRpc = createWebRPCHandler<Schema>(config);
|
|
168
169
|
return Object.assign(rpc, {
|
|
169
|
-
webHandler:
|
|
170
|
+
webHandler: webRpc,
|
|
171
|
+
webClients: webRpc.webClients,
|
|
172
|
+
broadcast: webRpc.broadcast,
|
|
170
173
|
});
|
|
171
174
|
}
|
|
172
175
|
|
package/src/shared/rpc.ts
CHANGED
|
@@ -80,6 +80,8 @@ export type BuniteRPCSchema = {
|
|
|
80
80
|
webview: RPCSchema;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
type RemoteSideOf<S extends "bun" | "webview"> = S extends "bun" ? "webview" : "bun";
|
|
84
|
+
|
|
83
85
|
export type BuniteRPCConfig<
|
|
84
86
|
Schema extends BuniteRPCSchema,
|
|
85
87
|
Side extends "bun" | "webview"
|
|
@@ -88,13 +90,13 @@ export type BuniteRPCConfig<
|
|
|
88
90
|
handlers: {
|
|
89
91
|
requests?: RPCRequestHandler<Schema[Side]["requests"]>;
|
|
90
92
|
messages?: {
|
|
91
|
-
[K in keyof Schema[Side]["messages"]]?: (
|
|
92
|
-
payload: MessagePayload<Schema[Side]["messages"], K>
|
|
93
|
+
[K in keyof Schema[RemoteSideOf<Side>]["messages"]]?: (
|
|
94
|
+
payload: MessagePayload<Schema[RemoteSideOf<Side>]["messages"], K>
|
|
93
95
|
) => void;
|
|
94
96
|
} & {
|
|
95
97
|
"*"?: (
|
|
96
|
-
messageName: keyof Schema[Side]["messages"],
|
|
97
|
-
payload: MessagePayload<Schema[Side]["messages"], keyof Schema[Side]["messages"]>
|
|
98
|
+
messageName: keyof Schema[RemoteSideOf<Side>]["messages"],
|
|
99
|
+
payload: MessagePayload<Schema[RemoteSideOf<Side>]["messages"], keyof Schema[RemoteSideOf<Side>]["messages"]>
|
|
98
100
|
) => void;
|
|
99
101
|
};
|
|
100
102
|
};
|
|
@@ -1,48 +1,92 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineBuniteRPC,
|
|
3
|
+
type BuniteRPCConfig,
|
|
4
|
+
type BuniteRPCSchema,
|
|
5
|
+
type RPCTransport,
|
|
6
|
+
type RPCPacket
|
|
7
|
+
} from "./rpc";
|
|
1
8
|
import { decodeRPCPacket, encodeRPCPacket, asUint8Array } from "./rpcWire";
|
|
2
9
|
|
|
3
|
-
type
|
|
10
|
+
type WebRPCSocket = { send(data: Uint8Array | ArrayBuffer): void | number };
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
export type WebRPCClient<Schema extends BuniteRPCSchema = BuniteRPCSchema> = {
|
|
13
|
+
ws: WebRPCSocket;
|
|
14
|
+
rpc: ReturnType<typeof defineBuniteRPC<Schema, "bun">>;
|
|
15
|
+
handlePacket: (packet: RPCPacket) => void | Promise<void>;
|
|
16
|
+
};
|
|
7
17
|
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
18
|
+
export function createWebRPCHandler<Schema extends BuniteRPCSchema>(
|
|
19
|
+
config: BuniteRPCConfig<Schema, "bun"> & {
|
|
20
|
+
extraRequestHandlers?: Record<string, (...args: any[]) => unknown>;
|
|
21
|
+
}
|
|
22
|
+
) {
|
|
23
|
+
const connections = new WeakMap<WebRPCSocket, WebRPCClient<Schema>>();
|
|
24
|
+
const webClients = new Set<WebRPCClient<Schema>>();
|
|
25
|
+
|
|
26
|
+
const handler = {
|
|
27
|
+
open(ws: WebRPCSocket) {
|
|
28
|
+
let handlePacket: ((packet: RPCPacket) => void | Promise<void>) | undefined;
|
|
29
|
+
|
|
30
|
+
const transport: RPCTransport = {
|
|
31
|
+
send(packet) {
|
|
32
|
+
ws.send(encodeRPCPacket(packet));
|
|
33
|
+
},
|
|
34
|
+
registerHandler(h) {
|
|
35
|
+
handlePacket = h;
|
|
36
|
+
},
|
|
37
|
+
unregisterHandler() {
|
|
38
|
+
handlePacket = undefined;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const rpc = defineBuniteRPC("bun", config);
|
|
43
|
+
rpc.setTransport(transport);
|
|
44
|
+
|
|
45
|
+
const client: WebRPCClient<Schema> = {
|
|
46
|
+
ws,
|
|
47
|
+
rpc: rpc as WebRPCClient<Schema>["rpc"],
|
|
48
|
+
handlePacket: (packet) => handlePacket?.(packet)
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
connections.set(ws, client);
|
|
52
|
+
webClients.add(client);
|
|
53
|
+
handler.onWebClientConnected?.(client);
|
|
54
|
+
},
|
|
11
55
|
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
message(ws: WebRPCSocket, raw: string | Buffer) {
|
|
56
|
+
message(ws: WebRPCSocket, raw: string | Buffer | ArrayBuffer | Uint8Array) {
|
|
15
57
|
if (typeof raw === "string") return;
|
|
16
58
|
|
|
17
|
-
|
|
59
|
+
const client = connections.get(ws);
|
|
60
|
+
if (!client) return;
|
|
61
|
+
|
|
18
62
|
try {
|
|
19
|
-
|
|
63
|
+
client.handlePacket(decodeRPCPacket(asUint8Array(raw)));
|
|
20
64
|
} catch {
|
|
21
|
-
|
|
65
|
+
// malformed packet
|
|
22
66
|
}
|
|
67
|
+
},
|
|
23
68
|
|
|
24
|
-
|
|
69
|
+
close(ws: WebRPCSocket) {
|
|
70
|
+
const client = connections.get(ws);
|
|
71
|
+
if (!client) return;
|
|
25
72
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
73
|
+
webClients.delete(client);
|
|
74
|
+
handler.onWebClientDisconnected?.(client);
|
|
75
|
+
client.rpc.setTransport({});
|
|
76
|
+
connections.delete(ws);
|
|
77
|
+
},
|
|
33
78
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
ws.send(encodeRPCPacket({ type: "response", id: packet.id, success: false, error: errorMessage(error) }))
|
|
40
|
-
);
|
|
41
|
-
} catch (error) {
|
|
42
|
-
ws.send(
|
|
43
|
-
encodeRPCPacket({ type: "response", id: packet.id, success: false, error: errorMessage(error) })
|
|
44
|
-
);
|
|
79
|
+
webClients: webClients as ReadonlySet<WebRPCClient<Schema>>,
|
|
80
|
+
|
|
81
|
+
broadcast(messageName: string, payload?: unknown) {
|
|
82
|
+
for (const client of webClients) {
|
|
83
|
+
(client.rpc.send as any)(messageName, payload);
|
|
45
84
|
}
|
|
46
|
-
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
onWebClientConnected: undefined as ((client: WebRPCClient<Schema>) => void) | undefined,
|
|
88
|
+
onWebClientDisconnected: undefined as ((client: WebRPCClient<Schema>) => void) | undefined,
|
|
47
89
|
};
|
|
90
|
+
|
|
91
|
+
return handler;
|
|
48
92
|
}
|