bunite-core 0.8.0 → 0.9.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.
Files changed (57) hide show
  1. package/package.json +9 -7
  2. package/src/{bun → host}/core/App.ts +45 -81
  3. package/src/{bun → host}/core/BrowserView.ts +64 -64
  4. package/src/{bun → host}/core/BrowserWindow.ts +14 -14
  5. package/src/host/core/Socket.ts +98 -0
  6. package/src/host/core/SurfaceBrowserIPC.ts +7 -0
  7. package/src/host/core/SurfaceManager.ts +154 -0
  8. package/src/host/encryptedPipe.ts +62 -0
  9. package/src/{bun → host}/events/appEvents.ts +0 -1
  10. package/src/host/index.ts +29 -0
  11. package/src/{bun/proc → host}/native.ts +38 -52
  12. package/src/{shared → host}/paths.ts +20 -26
  13. package/src/{bun/preload/inline.ts → host/preloadBundle.ts} +2 -2
  14. package/src/host/serveWeb.ts +81 -0
  15. package/src/native/linux/bunite_linux_runtime.cpp +2 -2
  16. package/src/native/mac/bunite_mac_ffi.mm +2 -2
  17. package/src/native/shared/ffi_exports.h +1 -1
  18. package/src/native/win/native_host_ffi.cpp +2 -2
  19. package/src/preload/runtime.built.js +1 -1
  20. package/src/preload/runtime.ts +54 -219
  21. package/src/preload/tsconfig.json +3 -10
  22. package/src/rpc/encrypt.ts +74 -0
  23. package/src/rpc/error.ts +58 -0
  24. package/src/rpc/framework.ts +132 -0
  25. package/src/rpc/hash.ts +142 -0
  26. package/src/rpc/index.ts +129 -0
  27. package/src/rpc/peer.ts +1055 -0
  28. package/src/rpc/renderer.ts +82 -0
  29. package/src/rpc/schema.ts +246 -0
  30. package/src/rpc/stream.ts +72 -0
  31. package/src/rpc/transport.ts +81 -0
  32. package/src/rpc/wire.ts +150 -0
  33. package/src/{preload/webviewElement.ts → webview/native.ts} +68 -48
  34. package/src/{shared/webviewPolyfill.ts → webview/polyfill.ts} +4 -7
  35. package/src/bun/core/Socket.ts +0 -187
  36. package/src/bun/core/SurfaceBrowserIPC.ts +0 -65
  37. package/src/bun/core/SurfaceManager.ts +0 -201
  38. package/src/bun/index.ts +0 -53
  39. package/src/bun/preload/index.ts +0 -73
  40. package/src/preload/tsconfig.tsbuildinfo +0 -1
  41. package/src/shared/rpc.ts +0 -424
  42. package/src/shared/rpcDemux.ts +0 -219
  43. package/src/shared/rpcWire.ts +0 -54
  44. package/src/shared/rpcWireConstants.ts +0 -3
  45. package/src/shared/webRpcHandler.ts +0 -77
  46. package/src/shared/webSocketTransport.ts +0 -26
  47. package/src/view/index.ts +0 -196
  48. /package/src/{shared → host}/cefVersion.ts +0 -0
  49. /package/src/{bun → host}/core/SurfaceRegistry.ts +0 -0
  50. /package/src/{bun → host}/core/singleInstanceLock.ts +0 -0
  51. /package/src/{bun → host}/core/windowIds.ts +0 -0
  52. /package/src/{bun → host}/events/event.ts +0 -0
  53. /package/src/{bun → host}/events/eventEmitter.ts +0 -0
  54. /package/src/{bun → host}/events/webviewEvents.ts +0 -0
  55. /package/src/{bun → host}/events/windowEvents.ts +0 -0
  56. /package/src/{shared → host}/log.ts +0 -0
  57. /package/src/{shared → host}/platform.ts +0 -0
@@ -1,219 +0,0 @@
1
- import type { RpcPacket, RpcTransport, RpcWithTransport } from "./rpc";
2
-
3
- type DemuxPacketEnvelope = { channel: string; packet: RpcPacket };
4
- type DemuxHelloFrame = { channel: string; hello: true };
5
- type DemuxFrame = DemuxPacketEnvelope | DemuxHelloFrame;
6
-
7
- function isDemuxFrame(value: unknown): value is DemuxFrame {
8
- if (typeof value !== "object" || value === null) return false;
9
- return typeof (value as DemuxFrame).channel === "string";
10
- }
11
-
12
- function isPacketEnvelope(frame: DemuxFrame): frame is DemuxPacketEnvelope {
13
- const v = frame as DemuxPacketEnvelope;
14
- return typeof v.packet === "object" && v.packet !== null;
15
- }
16
-
17
- function isHelloFrame(frame: DemuxFrame): frame is DemuxHelloFrame {
18
- return (frame as DemuxHelloFrame).hello === true;
19
- }
20
-
21
- export type RpcChannelHandle = {
22
- /**
23
- * Connect an RPC instance to this channel. Returns a promise that resolves
24
- * once both sides have registered a handler (HELLO handshake). Awaiting
25
- * guarantees the first subsequent request reaches the peer.
26
- */
27
- bindTo(rpc: RpcWithTransport): Promise<void>;
28
- };
29
-
30
- export type RpcTransportDemuxer = {
31
- channel(name: string): RpcChannelHandle;
32
- dispose(): void;
33
- };
34
-
35
- export type RpcDemuxBufferPolicy = "drop-oldest" | "drop-newest";
36
-
37
- export type RpcTransportDemuxerOptions = {
38
- /** ms to wait for peer before `bindTo` rejects. Default 10_000. */
39
- readyTimeout?: number;
40
- /**
41
- * Per-channel cap for packets received before a handler is registered.
42
- * Drained FIFO on registerHandler. Default 64. Set 0 to disable buffering.
43
- */
44
- bufferSize?: number;
45
- /** Overflow behaviour when bufferSize is exceeded. Default "drop-oldest". */
46
- bufferPolicy?: RpcDemuxBufferPolicy;
47
- };
48
-
49
- type ChannelState = {
50
- handler?: (packet: RpcPacket) => void;
51
- peerSawUs: boolean;
52
- ready: Promise<void>;
53
- resolveReady: () => void;
54
- rejectReady: (error: Error) => void;
55
- readySettled: boolean;
56
- readyTimer?: ReturnType<typeof setTimeout>;
57
- pending: RpcPacket[];
58
- };
59
-
60
- const DEFAULT_READY_TIMEOUT = 10_000;
61
- const DEFAULT_BUFFER_SIZE = 64;
62
-
63
- export function createRpcTransportDemuxer(
64
- base: RpcTransport,
65
- options: RpcTransportDemuxerOptions = {}
66
- ): RpcTransportDemuxer {
67
- if (!base.send || !base.registerHandler) {
68
- throw new Error("createRpcTransportDemuxer requires a base transport with both send and registerHandler");
69
- }
70
-
71
- const readyTimeout = options.readyTimeout ?? DEFAULT_READY_TIMEOUT;
72
- const bufferSize = Math.max(0, options.bufferSize ?? DEFAULT_BUFFER_SIZE);
73
- const bufferPolicy: RpcDemuxBufferPolicy = options.bufferPolicy ?? "drop-oldest";
74
- const channels = new Map<string, ChannelState>();
75
- let disposed = false;
76
-
77
- function getOrCreateState(name: string): ChannelState {
78
- let state = channels.get(name);
79
- if (state) return state;
80
-
81
- let resolveReady!: () => void;
82
- let rejectReady!: (error: Error) => void;
83
- const ready = new Promise<void>((resolve, reject) => {
84
- resolveReady = resolve;
85
- rejectReady = reject;
86
- });
87
- ready.catch(() => {}); // prevent unhandled rejection if consumer doesn't await
88
-
89
- state = {
90
- peerSawUs: false,
91
- ready,
92
- resolveReady,
93
- rejectReady,
94
- readySettled: false,
95
- pending: []
96
- };
97
- channels.set(name, state);
98
- return state;
99
- }
100
-
101
- function bufferIncoming(state: ChannelState, packet: RpcPacket) {
102
- if (bufferSize === 0) return;
103
- if (state.pending.length < bufferSize) {
104
- state.pending.push(packet);
105
- return;
106
- }
107
- if (bufferPolicy === "drop-oldest") {
108
- state.pending.shift();
109
- state.pending.push(packet);
110
- }
111
- // drop-newest: leave the queue alone, discard the new packet
112
- }
113
-
114
- function settleReady(state: ChannelState, action: () => void) {
115
- if (state.readySettled) return;
116
- state.readySettled = true;
117
- if (state.readyTimer) clearTimeout(state.readyTimer);
118
- action();
119
- }
120
-
121
- function sendHello(name: string) {
122
- const frame: DemuxHelloFrame = { channel: name, hello: true };
123
- base.send!(frame as unknown as RpcPacket);
124
- }
125
-
126
- base.registerHandler((data) => {
127
- if (!isDemuxFrame(data)) return;
128
- const state = getOrCreateState(data.channel);
129
-
130
- if (isHelloFrame(data)) {
131
- if (state.handler) {
132
- const wasReady = state.readySettled;
133
- settleReady(state, state.resolveReady);
134
- if (!wasReady && !disposed) sendHello(data.channel); // echo so peer wakes up
135
- } else {
136
- state.peerSawUs = true;
137
- }
138
- return;
139
- }
140
-
141
- if (isPacketEnvelope(data)) {
142
- if (state.handler) {
143
- state.handler(data.packet);
144
- } else {
145
- bufferIncoming(state, data.packet);
146
- }
147
- }
148
- });
149
-
150
- return {
151
- channel(name) {
152
- if (disposed) throw new Error(`Demuxer disposed; cannot open channel "${name}"`);
153
- const state = getOrCreateState(name);
154
-
155
- const transport: RpcTransport = {
156
- send(packet) {
157
- if (disposed) throw new Error(`Demuxer disposed; cannot send on channel "${name}"`);
158
- const envelope: DemuxPacketEnvelope = { channel: name, packet };
159
- base.send!(envelope as unknown as RpcPacket);
160
- },
161
- registerHandler(handler) {
162
- if (disposed) throw new Error(`Demuxer disposed; cannot register on channel "${name}"`);
163
- if (state.handler) {
164
- throw new Error(`Channel "${name}" already has a handler on this demuxer`);
165
- }
166
- state.handler = handler;
167
-
168
- sendHello(name);
169
-
170
- if (state.peerSawUs) {
171
- settleReady(state, state.resolveReady);
172
- } else if (!state.readySettled && !state.readyTimer) {
173
- state.readyTimer = setTimeout(() => {
174
- settleReady(state, () =>
175
- state.rejectReady(new Error(`Channel "${name}" ready timed out after ${readyTimeout}ms`))
176
- );
177
- }, readyTimeout);
178
- }
179
-
180
- // Drain after handshake bookkeeping so a thrown handler doesn't
181
- // leave HELLO unsent or the ready promise un-armed. Handler errors
182
- // during drain are swallowed so one bad packet doesn't drop the rest;
183
- // synchronous throws from RPC handlers are a consumer bug.
184
- if (state.pending.length > 0) {
185
- const drained = state.pending;
186
- state.pending = [];
187
- for (const packet of drained) {
188
- try { handler(packet); } catch { /* drain continues */ }
189
- }
190
- }
191
- },
192
- unregisterHandler() {
193
- state.handler = undefined;
194
- }
195
- };
196
-
197
- return {
198
- bindTo(rpc) {
199
- rpc.setTransport(transport);
200
- return state.ready;
201
- }
202
- };
203
- },
204
- dispose() {
205
- if (disposed) return;
206
- disposed = true;
207
- for (const state of channels.values()) {
208
- if (state.readyTimer) clearTimeout(state.readyTimer);
209
- if (!state.readySettled) {
210
- state.readySettled = true;
211
- state.rejectReady(new Error("Demuxer disposed"));
212
- }
213
- state.pending.length = 0;
214
- }
215
- channels.clear();
216
- base.unregisterHandler?.();
217
- }
218
- };
219
- }
@@ -1,54 +0,0 @@
1
- import { pack, unpack } from "msgpackr";
2
- import type { RpcPacket } from "./rpc";
3
- import {
4
- RPC_AUTH_TAG_LENGTH,
5
- RPC_FRAME_VERSION,
6
- RPC_IV_LENGTH
7
- } from "./rpcWireConstants";
8
-
9
- export function encodeRpcPacket(packet: RpcPacket): Uint8Array {
10
- return pack(packet) as Uint8Array;
11
- }
12
-
13
- export function decodeRpcPacket(data: Uint8Array): RpcPacket {
14
- return unpack(data) as RpcPacket;
15
- }
16
-
17
- export function createEncryptedRpcFrame(
18
- iv: Uint8Array,
19
- encryptedPayload: Uint8Array
20
- ): Uint8Array {
21
- if (iv.byteLength !== RPC_IV_LENGTH) {
22
- throw new Error(`Invalid RPC IV length: expected ${RPC_IV_LENGTH}, got ${iv.byteLength}`);
23
- }
24
-
25
- const frame = new Uint8Array(1 + RPC_IV_LENGTH + encryptedPayload.byteLength);
26
- frame[0] = RPC_FRAME_VERSION;
27
- frame.set(iv, 1);
28
- frame.set(encryptedPayload, 1 + RPC_IV_LENGTH);
29
- return frame;
30
- }
31
-
32
- export function parseEncryptedRpcFrame(frame: Uint8Array) {
33
- if (frame.byteLength < 1 + RPC_IV_LENGTH + RPC_AUTH_TAG_LENGTH) {
34
- throw new Error("Invalid RPC frame: payload is too short.");
35
- }
36
- if (frame[0] !== RPC_FRAME_VERSION) {
37
- throw new Error(`Unsupported RPC frame version: ${frame[0]}`);
38
- }
39
-
40
- return {
41
- iv: frame.subarray(1, 1 + RPC_IV_LENGTH),
42
- encryptedPayload: frame.subarray(1 + RPC_IV_LENGTH)
43
- };
44
- }
45
-
46
- export function asUint8Array(data: ArrayBuffer | ArrayBufferView | Uint8Array): Uint8Array {
47
- if (data instanceof Uint8Array) {
48
- return data;
49
- }
50
- if (ArrayBuffer.isView(data)) {
51
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
52
- }
53
- return new Uint8Array(data);
54
- }
@@ -1,3 +0,0 @@
1
- export const RPC_FRAME_VERSION = 1;
2
- export const RPC_IV_LENGTH = 12;
3
- export const RPC_AUTH_TAG_LENGTH = 16;
@@ -1,77 +0,0 @@
1
- import {
2
- defineBunRpc,
3
- type BuniteRpcConfig,
4
- type BuniteRpcSchema
5
- } from "./rpc";
6
- import { createWebSocketTransport, type WebSocketLike } from "./webSocketTransport";
7
- import { log } from "./log";
8
-
9
- export type WebRpcClient<Schema extends BuniteRpcSchema = BuniteRpcSchema> = {
10
- ws: WebSocketLike;
11
- rpc: ReturnType<typeof defineBunRpc<Schema>>;
12
- };
13
-
14
- export function createWebRpcHandler<Schema extends BuniteRpcSchema>(
15
- config: BuniteRpcConfig<Schema, "bun">
16
- ) {
17
- type Entry = { client: WebRpcClient<Schema>; receive: (raw: ArrayBuffer | Uint8Array) => void };
18
-
19
- const connections = new WeakMap<WebSocketLike, Entry>();
20
- const webClients = new Set<WebRpcClient<Schema>>();
21
-
22
- const handler = {
23
- open(ws: WebSocketLike) {
24
- const pipe = createWebSocketTransport(ws);
25
- const rpc = defineBunRpc(config);
26
- rpc.setTransport(pipe.transport);
27
-
28
- const client: WebRpcClient<Schema> = { ws, rpc: rpc as WebRpcClient<Schema>["rpc"] };
29
-
30
- connections.set(ws, { client, receive: pipe.receive });
31
- webClients.add(client);
32
- handler.onWebClientConnected?.(client);
33
- },
34
-
35
- message(ws: WebSocketLike, raw: string | Buffer | ArrayBuffer | Uint8Array) {
36
- if (typeof raw === "string") return;
37
- const entry = connections.get(ws);
38
- if (!entry) return;
39
-
40
- try {
41
- entry.receive(raw);
42
- } catch (error) {
43
- log.error("Web RPC packet handler error", error);
44
- }
45
- },
46
-
47
- close(ws: WebSocketLike) {
48
- const entry = connections.get(ws);
49
- if (!entry) return;
50
-
51
- entry.client.rpc.dispose();
52
- webClients.delete(entry.client);
53
- connections.delete(ws);
54
- handler.onWebClientDisconnected?.(entry.client);
55
- },
56
-
57
- webClients: webClients as ReadonlySet<WebRpcClient<Schema>>,
58
-
59
- broadcast<M extends keyof Schema["bun"]["messages"]>(
60
- messageName: M,
61
- ...args: void extends Schema["bun"]["messages"][M]
62
- ? []
63
- : undefined extends Schema["bun"]["messages"][M]
64
- ? [payload?: Schema["bun"]["messages"][M]]
65
- : [payload: Schema["bun"]["messages"][M]]
66
- ) {
67
- for (const client of webClients) {
68
- (client.rpc.send as any)(messageName, ...args);
69
- }
70
- },
71
-
72
- onWebClientConnected: undefined as ((client: WebRpcClient<Schema>) => void) | undefined,
73
- onWebClientDisconnected: undefined as ((client: WebRpcClient<Schema>) => void) | undefined,
74
- };
75
-
76
- return handler;
77
- }
@@ -1,26 +0,0 @@
1
- import type { RpcPacket, RpcTransport } from "./rpc";
2
- import { asUint8Array, decodeRpcPacket, encodeRpcPacket } from "./rpcWire";
3
-
4
- export type WebSocketLike = {
5
- send(data: Uint8Array | ArrayBuffer): void | number;
6
- };
7
-
8
- export type WebSocketTransportPipe = {
9
- transport: RpcTransport;
10
- receive(raw: ArrayBuffer | ArrayBufferView | Uint8Array): void;
11
- };
12
-
13
- export function createWebSocketTransport(ws: WebSocketLike): WebSocketTransportPipe {
14
- let handler: ((packet: RpcPacket) => void) | undefined;
15
-
16
- return {
17
- transport: {
18
- send(packet) { ws.send(encodeRpcPacket(packet)); },
19
- registerHandler(h) { handler = h; },
20
- unregisterHandler() { handler = undefined; }
21
- },
22
- receive(raw) {
23
- handler?.(decodeRpcPacket(asUint8Array(raw)));
24
- }
25
- };
26
- }
package/src/view/index.ts DELETED
@@ -1,196 +0,0 @@
1
- import { registerBuniteWebviewPolyfill } from "../shared/webviewPolyfill";
2
- import {
3
- defineWebviewRpc,
4
- type BuniteRpcConfig,
5
- type RpcPacket,
6
- type BuniteRpcSchema,
7
- type RpcSchema,
8
- type RpcTransport,
9
- type RpcWithTransport
10
- } from "../shared/rpc";
11
- import { createRpcTransportDemuxer, type RpcChannelHandle, type RpcTransportDemuxer, type RpcTransportDemuxerOptions } from "../shared/rpcDemux";
12
- import { createWebSocketTransport, type WebSocketLike, type WebSocketTransportPipe } from "../shared/webSocketTransport";
13
- import { decodeRpcPacket, encodeRpcPacket } from "../shared/rpcWire";
14
- import { log } from "../shared/log";
15
-
16
- type BuniteWindowGlobals = Window &
17
- typeof globalThis & {
18
- __buniteWebviewId?: number;
19
- __buniteRpcSocketPort?: number;
20
- __bunite?: {
21
- receiveMessageFromBun?: (message: unknown) => void;
22
- };
23
- __bunite_encrypt?: (data: Uint8Array) => Promise<Uint8Array>;
24
- __bunite_decrypt?: (data: Uint8Array) => Promise<Uint8Array>;
25
- };
26
-
27
- type BuniteEnv = {
28
- window: BuniteWindowGlobals | null;
29
- webviewId: number | undefined;
30
- rpcPort: number | undefined;
31
- isNative: boolean;
32
- };
33
-
34
- function readBuniteEnv(): BuniteEnv {
35
- const w = typeof window !== "undefined" ? (window as BuniteWindowGlobals) : null;
36
- const webviewId = w?.__buniteWebviewId;
37
- const rpcPort = w?.__buniteRpcSocketPort;
38
- return { window: w, webviewId, rpcPort, isNative: webviewId != null && rpcPort != null };
39
- }
40
-
41
- function toArrayBuffer(bytes: Uint8Array): ArrayBuffer {
42
- const copy = new Uint8Array(bytes.byteLength);
43
- copy.set(bytes);
44
- return copy.buffer;
45
- }
46
-
47
- export class BuniteView<T extends RpcWithTransport = RpcWithTransport> {
48
- bunSocket?: WebSocket;
49
- rpc?: T;
50
- readonly transport: RpcTransport;
51
-
52
- private env: BuniteEnv;
53
- private handler?: (packet: RpcPacket) => void;
54
- private pendingPackets: RpcPacket[] = [];
55
-
56
- constructor(config?: { rpc?: T }) {
57
- registerBuniteWebviewPolyfill();
58
- this.env = readBuniteEnv();
59
- this.rpc = config?.rpc;
60
-
61
- this.transport = {
62
- send: (packet) => {
63
- if (this.bunSocket?.readyState === WebSocket.OPEN) {
64
- this.sendPacket(packet);
65
- } else if (this.bunSocket?.readyState === WebSocket.CONNECTING) {
66
- this.pendingPackets.push(packet);
67
- }
68
- },
69
- registerHandler: (h) => { this.handler = h; },
70
- unregisterHandler: () => { this.handler = undefined; }
71
- };
72
-
73
- this.initSocketToBun();
74
- if (this.env.isNative && this.env.window) {
75
- this.env.window.__bunite ??= {};
76
- this.env.window.__bunite.receiveMessageFromBun = (message) => {
77
- this.handler?.(message as RpcPacket);
78
- };
79
- }
80
- this.rpc?.setTransport(this.transport);
81
- }
82
-
83
- private sendPacket(packet: RpcPacket) {
84
- if (this.env.isNative) {
85
- void this.bunBridge(packet).catch((error) => {
86
- log.error("Failed to send RPC packet", error);
87
- });
88
- } else {
89
- this.bunSocket!.send(toArrayBuffer(encodeRpcPacket(packet)));
90
- }
91
- }
92
-
93
- initSocketToBun() {
94
- if (!this.env.isNative) {
95
- const proto = location.protocol === "https:" ? "wss:" : "ws:";
96
- const socket = new WebSocket(`${proto}//${location.host}/rpc`);
97
- socket.binaryType = "arraybuffer";
98
- this.bunSocket = socket;
99
-
100
- socket.addEventListener("message", async (event) => {
101
- const bytes = await messageToUint8Array(event.data);
102
- if (!bytes) return;
103
- try {
104
- this.handler?.(decodeRpcPacket(bytes));
105
- } catch (error) {
106
- log.error("Failed to parse WebSocket message", error);
107
- }
108
- });
109
- } else {
110
- // Share a single WebSocket with the preload's bunite.invoke.
111
- const globals = this.env.window as any;
112
- globals.__bunite ??= {};
113
- const existing = globals.__bunite._socket;
114
- if (existing && existing.readyState <= WebSocket.OPEN) {
115
- this.bunSocket = existing;
116
- } else {
117
- const socket = new WebSocket(
118
- `ws://localhost:${this.env.rpcPort}/socket?webviewId=${this.env.webviewId}`
119
- );
120
- socket.binaryType = "arraybuffer";
121
- this.bunSocket = socket;
122
- globals.__bunite._socket = socket;
123
- }
124
-
125
- this.bunSocket!.addEventListener("message", async (event) => {
126
- const binaryMessage = await messageToUint8Array(event.data);
127
- if (!binaryMessage) return;
128
-
129
- try {
130
- const decrypt = this.env.window?.__bunite_decrypt;
131
- if (!decrypt) {
132
- log.error("No decrypt function available in preload globals");
133
- return;
134
- }
135
- const decrypted = await decrypt(binaryMessage);
136
- const packet = decodeRpcPacket(decrypted);
137
- if ((packet as any).scope === "global") return;
138
- this.handler?.(packet);
139
- } catch (error) {
140
- log.error("Failed to parse message from Bun", error);
141
- }
142
- });
143
- }
144
-
145
- this.bunSocket!.addEventListener("open", () => {
146
- for (const packet of this.pendingPackets) this.sendPacket(packet);
147
- this.pendingPackets = [];
148
- });
149
-
150
- this.bunSocket!.addEventListener("error", () => {
151
- log.error("RPC WebSocket error");
152
- });
153
-
154
- this.bunSocket!.addEventListener("close", () => {
155
- if (this.pendingPackets.length > 0) {
156
- log.error(`RPC WebSocket closed with ${this.pendingPackets.length} pending packets`);
157
- this.pendingPackets = [];
158
- }
159
- });
160
- }
161
-
162
- async bunBridge(message: RpcPacket) {
163
- if (this.bunSocket?.readyState !== WebSocket.OPEN) return;
164
-
165
- const encrypt = this.env.window?.__bunite_encrypt;
166
- if (!encrypt) {
167
- log.error("No encrypt function available in preload globals");
168
- return;
169
- }
170
-
171
- const encrypted = await encrypt(encodeRpcPacket(message));
172
- this.bunSocket.send(toArrayBuffer(encrypted));
173
- }
174
-
175
- }
176
-
177
- async function messageToUint8Array(data: unknown) {
178
- if (data instanceof ArrayBuffer) return new Uint8Array(data);
179
- if (data instanceof Blob) return new Uint8Array(await data.arrayBuffer());
180
- if (data instanceof Uint8Array) return data;
181
- return null;
182
- }
183
-
184
- export { log, type LogLevel } from "../shared/log";
185
- export { createRpcTransportDemuxer, createWebSocketTransport, defineWebviewRpc, registerBuniteWebviewPolyfill };
186
-
187
- export type {
188
- BuniteRpcConfig,
189
- BuniteRpcSchema,
190
- RpcChannelHandle,
191
- RpcSchema,
192
- RpcTransportDemuxer,
193
- RpcTransportDemuxerOptions,
194
- WebSocketLike,
195
- WebSocketTransportPipe
196
- };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes