electrobun 1.18.4-beta.6 → 2.0.1-beta.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -170
  3. package/bin/electrobun.cjs +230 -153
  4. package/package.json +18 -49
  5. package/bun.lock +0 -119
  6. package/dist/api/browser/builtinrpcSchema.ts +0 -19
  7. package/dist/api/browser/global.d.ts +0 -36
  8. package/dist/api/browser/index.ts +0 -234
  9. package/dist/api/browser/webviewtag.ts +0 -88
  10. package/dist/api/browser/wgputag.ts +0 -48
  11. package/dist/api/bun/ElectrobunConfig.ts +0 -530
  12. package/dist/api/bun/__tests__/ffi-contract.test.ts +0 -105
  13. package/dist/api/bun/core/ApplicationMenu.ts +0 -70
  14. package/dist/api/bun/core/BrowserView.ts +0 -419
  15. package/dist/api/bun/core/BrowserWindow.ts +0 -400
  16. package/dist/api/bun/core/BuildConfig.ts +0 -71
  17. package/dist/api/bun/core/ContextMenu.ts +0 -75
  18. package/dist/api/bun/core/GpuWindow.ts +0 -289
  19. package/dist/api/bun/core/Paths.ts +0 -5
  20. package/dist/api/bun/core/Socket.ts +0 -22
  21. package/dist/api/bun/core/Tray.ts +0 -197
  22. package/dist/api/bun/core/Updater.ts +0 -1162
  23. package/dist/api/bun/core/Utils.ts +0 -487
  24. package/dist/api/bun/core/WGPUView.ts +0 -167
  25. package/dist/api/bun/core/menuRoles.ts +0 -181
  26. package/dist/api/bun/events/ApplicationEvents.ts +0 -22
  27. package/dist/api/bun/events/event.ts +0 -29
  28. package/dist/api/bun/events/eventEmitter.ts +0 -45
  29. package/dist/api/bun/events/trayEvents.ts +0 -11
  30. package/dist/api/bun/events/webviewEvents.ts +0 -39
  31. package/dist/api/bun/events/windowEvents.ts +0 -23
  32. package/dist/api/bun/index.ts +0 -298
  33. package/dist/api/bun/preload/.generated/compiled.ts +0 -8
  34. package/dist/api/bun/preload/build.ts +0 -65
  35. package/dist/api/bun/preload/dragRegions.ts +0 -41
  36. package/dist/api/bun/preload/encryption.ts +0 -86
  37. package/dist/api/bun/preload/events.ts +0 -171
  38. package/dist/api/bun/preload/globals.d.ts +0 -45
  39. package/dist/api/bun/preload/index-sandboxed.ts +0 -28
  40. package/dist/api/bun/preload/index.ts +0 -77
  41. package/dist/api/bun/preload/internalRpc.ts +0 -80
  42. package/dist/api/bun/preload/overlaySync.ts +0 -107
  43. package/dist/api/bun/preload/webviewTag.ts +0 -451
  44. package/dist/api/bun/preload/wgpuTag.ts +0 -246
  45. package/dist/api/bun/proc/linux.md +0 -43
  46. package/dist/api/bun/proc/native.ts +0 -3385
  47. package/dist/api/bun/webGPU.ts +0 -346
  48. package/dist/api/bun/webgpuAdapter.ts +0 -3011
  49. package/dist/api/shared/bun-version.ts +0 -3
  50. package/dist/api/shared/cef-version.ts +0 -5
  51. package/dist/api/shared/electrobun-version.ts +0 -2
  52. package/dist/api/shared/naming.test.ts +0 -327
  53. package/dist/api/shared/naming.ts +0 -188
  54. package/dist/api/shared/platform.ts +0 -48
  55. package/dist/api/shared/rpc.ts +0 -541
  56. package/dist/main.js +0 -168
  57. package/dist/preload-full.js +0 -913
  58. package/dist/preload-sandboxed.js +0 -111
  59. package/dist/zig-sdk/electrobun.zig +0 -1993
  60. package/src/cli/bun.lockb +0 -0
  61. package/src/cli/index.ts +0 -5689
  62. package/src/cli/package-lock.json +0 -81
  63. package/src/cli/package.json +0 -11
@@ -1,289 +0,0 @@
1
- import { ffi } from "../proc/native";
2
- import electrobunEventEmitter from "../events/eventEmitter";
3
- import { type Pointer } from "bun:ffi";
4
- import { WGPUView } from "./WGPUView";
5
- import { BuildConfig } from "./BuildConfig";
6
-
7
-
8
- export type GpuWindowOptionsType = {
9
- trafficLightOffset?: {
10
- x: number;
11
- y: number;
12
- };
13
- activate?: boolean;
14
- title: string;
15
- frame: {
16
- x: number;
17
- y: number;
18
- width: number;
19
- height: number;
20
- };
21
- styleMask?: {};
22
- titleBarStyle: "hidden" | "hiddenInset" | "default";
23
- transparent: boolean;
24
- };
25
-
26
- const defaultOptions: GpuWindowOptionsType = {
27
- title: "Electrobun",
28
- frame: {
29
- x: 0,
30
- y: 0,
31
- width: 800,
32
- height: 600,
33
- },
34
- titleBarStyle: "default",
35
- transparent: false,
36
- };
37
-
38
- const buildConfig = BuildConfig.getSync();
39
- ffi.request.setExitOnLastWindowClosed({
40
- enabled: buildConfig.runtime?.exitOnLastWindowClosed ?? true,
41
- });
42
-
43
- export const GpuWindowMap: {
44
- [id: number]: GpuWindow;
45
- } = {};
46
-
47
- // Clean up JS wrapper state when a window closes. Native child cleanup is core-owned.
48
- electrobunEventEmitter.on("close", (event: { data: { id: number } }) => {
49
- const windowId = event.data.id;
50
- delete GpuWindowMap[windowId];
51
-
52
- // Clean up all WGPU views associated with this window
53
- for (const view of WGPUView.getAll()) {
54
- if (view.windowId === windowId) {
55
- view.remove();
56
- }
57
- }
58
-
59
- });
60
-
61
- export class GpuWindow {
62
- id = 0;
63
- title: string = "Electrobun";
64
- state: "creating" | "created" = "creating";
65
- transparent: boolean = false;
66
- trafficLightOffset: { x: number; y: number } = { x: 0, y: 0 };
67
- frame: {
68
- x: number;
69
- y: number;
70
- width: number;
71
- height: number;
72
- } = {
73
- x: 0,
74
- y: 0,
75
- width: 800,
76
- height: 600,
77
- };
78
- wgpuViewId!: number;
79
-
80
- get ptr(): Pointer | null {
81
- return ffi.request.getWindowPointer({ winId: this.id }) as Pointer | null;
82
- }
83
-
84
- constructor(options: Partial<GpuWindowOptionsType> = defaultOptions) {
85
- this.title = options.title || "New Window";
86
- this.frame = options.frame
87
- ? { ...defaultOptions.frame, ...options.frame }
88
- : { ...defaultOptions.frame };
89
- this.transparent = options.transparent ?? false;
90
- this.trafficLightOffset = {
91
- x: options.trafficLightOffset?.x ?? 0,
92
- y: options.trafficLightOffset?.y ?? 0,
93
- };
94
-
95
- this.init(options);
96
- }
97
-
98
- init({
99
- styleMask,
100
- titleBarStyle,
101
- transparent,
102
- activate,
103
- }: Partial<GpuWindowOptionsType>) {
104
- const windowId = ffi.request.createWindow({
105
- title: this.title,
106
- url: "",
107
- frame: {
108
- width: this.frame.width,
109
- height: this.frame.height,
110
- x: this.frame.x,
111
- y: this.frame.y,
112
- },
113
- styleMask: {
114
- Borderless: false,
115
- Titled: true,
116
- Closable: true,
117
- Miniaturizable: true,
118
- Resizable: true,
119
- UnifiedTitleAndToolbar: false,
120
- FullScreen: false,
121
- FullSizeContentView: false,
122
- UtilityWindow: false,
123
- DocModalWindow: false,
124
- NonactivatingPanel: false,
125
- HUDWindow: false,
126
- ...(styleMask || {}),
127
- // hiddenInset: transparent titlebar with inset native controls
128
- ...(titleBarStyle === "hiddenInset"
129
- ? {
130
- Titled: true,
131
- FullSizeContentView: true,
132
- }
133
- : {}),
134
- // hidden: no titlebar, no native controls (for fully custom chrome)
135
- ...(titleBarStyle === "hidden"
136
- ? {
137
- Titled: false,
138
- FullSizeContentView: true,
139
- }
140
- : {}),
141
- },
142
- titleBarStyle: titleBarStyle || "default",
143
- transparent: transparent ?? false,
144
- activate: activate ?? true,
145
- trafficLightOffset: this.trafficLightOffset,
146
- });
147
-
148
- if (!windowId) {
149
- throw "Failed to create window";
150
- }
151
-
152
- this.id = windowId as number;
153
-
154
- GpuWindowMap[this.id] = this;
155
-
156
- const wgpuView = new WGPUView({
157
- frame: {
158
- x: 0,
159
- y: 0,
160
- width: this.frame.width,
161
- height: this.frame.height,
162
- },
163
- windowId: this.id,
164
- autoResize: true,
165
- startTransparent: false,
166
- startPassthrough: false,
167
- });
168
-
169
- this.wgpuViewId = wgpuView.id;
170
- }
171
-
172
- get wgpuView() {
173
- return WGPUView.getById(this.wgpuViewId) as WGPUView;
174
- }
175
-
176
- static getById(id: number) {
177
- return GpuWindowMap[id];
178
- }
179
-
180
- setTitle(title: string) {
181
- this.title = title;
182
- return ffi.request.setTitle({ winId: this.id, title });
183
- }
184
-
185
- close() {
186
- return ffi.request.closeWindow({ winId: this.id });
187
- }
188
-
189
- activate() {
190
- return ffi.request.activateWindow({ winId: this.id });
191
- }
192
-
193
- focus() {
194
- console.log(
195
- "[electrobun] GpuWindow.focus() is deprecated. Use window.activate() instead.",
196
- );
197
- return this.activate();
198
- }
199
-
200
- show() {
201
- return ffi.request.showWindow({ winId: this.id, activate: true });
202
- }
203
-
204
- showInactive() {
205
- return ffi.request.showWindow({ winId: this.id, activate: false });
206
- }
207
-
208
- minimize() {
209
- return ffi.request.minimizeWindow({ winId: this.id });
210
- }
211
-
212
- unminimize() {
213
- return ffi.request.restoreWindow({ winId: this.id });
214
- }
215
-
216
- isMinimized(): boolean {
217
- return ffi.request.isWindowMinimized({ winId: this.id });
218
- }
219
-
220
- maximize() {
221
- return ffi.request.maximizeWindow({ winId: this.id });
222
- }
223
-
224
- unmaximize() {
225
- return ffi.request.unmaximizeWindow({ winId: this.id });
226
- }
227
-
228
- isMaximized(): boolean {
229
- return ffi.request.isWindowMaximized({ winId: this.id });
230
- }
231
-
232
- setFullScreen(fullScreen: boolean) {
233
- return ffi.request.setWindowFullScreen({ winId: this.id, fullScreen });
234
- }
235
-
236
- isFullScreen(): boolean {
237
- return ffi.request.isWindowFullScreen({ winId: this.id });
238
- }
239
-
240
- setAlwaysOnTop(alwaysOnTop: boolean) {
241
- return ffi.request.setWindowAlwaysOnTop({ winId: this.id, alwaysOnTop });
242
- }
243
-
244
- isAlwaysOnTop(): boolean {
245
- return ffi.request.isWindowAlwaysOnTop({ winId: this.id });
246
- }
247
-
248
- setPosition(x: number, y: number) {
249
- this.frame.x = x;
250
- this.frame.y = y;
251
- return ffi.request.setWindowPosition({ winId: this.id, x, y });
252
- }
253
-
254
- setWindowButtonPosition(x: number, y: number) {
255
- return ffi.request.setWindowButtonPosition({ winId: this.id, x, y });
256
- }
257
-
258
- setSize(width: number, height: number) {
259
- this.frame.width = width;
260
- this.frame.height = height;
261
- return ffi.request.setWindowSize({ winId: this.id, width, height });
262
- }
263
-
264
- setFrame(x: number, y: number, width: number, height: number) {
265
- this.frame = { x, y, width, height };
266
- return ffi.request.setWindowFrame({ winId: this.id, x, y, width, height });
267
- }
268
-
269
- getFrame(): { x: number; y: number; width: number; height: number } {
270
- const frame = ffi.request.getWindowFrame({ winId: this.id });
271
- this.frame = frame;
272
- return frame;
273
- }
274
-
275
- getPosition(): { x: number; y: number } {
276
- const frame = this.getFrame();
277
- return { x: frame.x, y: frame.y };
278
- }
279
-
280
- getSize(): { width: number; height: number } {
281
- const frame = this.getFrame();
282
- return { width: frame.width, height: frame.height };
283
- }
284
-
285
- on(name: string, handler: (event: unknown) => void) {
286
- const specificName = `${name}-${this.id}`;
287
- electrobunEventEmitter.on(specificName, handler);
288
- }
289
- }
@@ -1,5 +0,0 @@
1
- import { resolve } from "path";
2
-
3
- export const RESOURCES_FOLDER = resolve("../Resources/");
4
-
5
- export const VIEWS_FOLDER = resolve(RESOURCES_FOLDER, "app/views");
@@ -1,22 +0,0 @@
1
- import { ffi } from "../proc/native";
2
-
3
- export const removeSocketForWebview = (webviewId: number) => {
4
- ffi.request.clearWebviewHostTransport({ id: webviewId });
5
- };
6
-
7
- // Will return true if message was sent over the core-owned websocket transport.
8
- // False means the caller should fall back to the native bridge / evaluateJS path.
9
- export const sendMessageToWebviewViaSocket = (
10
- webviewId: number,
11
- message: unknown,
12
- ): boolean => {
13
- try {
14
- return ffi.request.sendHostMessageToWebviewViaTransport({
15
- id: webviewId,
16
- messageJson: JSON.stringify(message),
17
- }) as boolean;
18
- } catch (error) {
19
- console.error("Error sending message to webview via host transport:", error);
20
- return false;
21
- }
22
- };
@@ -1,197 +0,0 @@
1
- import { ffi, type MenuItemConfig, type Rectangle } from "../proc/native";
2
- import electrobunEventEmitter from "../events/eventEmitter";
3
- import { VIEWS_FOLDER } from "./Paths";
4
- import { join } from "path";
5
-
6
- type NonDividerMenuItem = Exclude<
7
- MenuItemConfig,
8
- { type: "divider" | "separator" }
9
- >;
10
-
11
- const TrayMap: { [id: number]: Tray } = {};
12
-
13
- export type TrayOptions = {
14
- title?: string;
15
- image?: string;
16
- template?: boolean;
17
- width?: number;
18
- height?: number;
19
- };
20
-
21
- export class Tray {
22
- id = 0;
23
- visible = false;
24
- title = "";
25
- image = "";
26
- template = true;
27
- width = 16;
28
- height = 16;
29
- menu: Array<MenuItemConfig> | null = null;
30
-
31
- constructor({
32
- title = "",
33
- image = "",
34
- template = true,
35
- width = 16,
36
- height = 16,
37
- }: TrayOptions = {}) {
38
- this.title = title;
39
- this.image = image;
40
- this.template = template;
41
- this.width = width;
42
- this.height = height;
43
-
44
- if (this.createNativeTray()) {
45
- TrayMap[this.id] = this;
46
- }
47
- }
48
-
49
- private createNativeTray(): boolean {
50
- try {
51
- const trayId = ffi.request.createTray({
52
- title: this.title,
53
- image: this.resolveImagePath(this.image),
54
- template: this.template,
55
- width: this.width,
56
- height: this.height,
57
- }) as number;
58
-
59
- if (!trayId) {
60
- throw new Error("Tray creation returned an invalid id");
61
- }
62
-
63
- this.id = trayId;
64
- this.visible = true;
65
- return true;
66
- } catch (error) {
67
- console.warn("Tray creation failed:", error);
68
- console.warn(
69
- "System tray functionality may not be available on this platform",
70
- );
71
- this.visible = false;
72
- return false;
73
- }
74
- }
75
-
76
- resolveImagePath(imgPath: string) {
77
- if (imgPath.startsWith("views://")) {
78
- return join(VIEWS_FOLDER, imgPath.replace("views://", ""));
79
- } else {
80
- // can specify any file path here
81
- return imgPath;
82
- }
83
- }
84
-
85
- setTitle(title: string) {
86
- this.title = title;
87
- if (!this.id) return;
88
- ffi.request.setTrayTitle({ id: this.id, title });
89
- }
90
-
91
- setImage(imgPath: string) {
92
- this.image = imgPath;
93
- if (!this.id) return;
94
- ffi.request.setTrayImage({
95
- id: this.id,
96
- image: this.resolveImagePath(imgPath),
97
- });
98
- }
99
-
100
- setMenu(menu: Array<MenuItemConfig>) {
101
- this.menu = menu;
102
- if (!this.id) return;
103
- const menuWithDefaults = menuConfigWithDefaults(menu);
104
- ffi.request.setTrayMenu({
105
- id: this.id,
106
- menuConfig: JSON.stringify(menuWithDefaults),
107
- });
108
- }
109
-
110
- on(name: "tray-clicked", handler: (event: unknown) => void) {
111
- const specificName = `${name}-${this.id}`;
112
- electrobunEventEmitter.on(specificName, handler);
113
- }
114
-
115
- setVisible(visible: boolean) {
116
- if (visible === this.visible) {
117
- return;
118
- }
119
-
120
- if (!visible) {
121
- if (this.id) ffi.request.hideTray({ id: this.id });
122
- this.visible = false;
123
- return;
124
- }
125
-
126
- if (!this.id) {
127
- if (this.createNativeTray()) {
128
- TrayMap[this.id] = this;
129
- }
130
- return;
131
- }
132
-
133
- this.visible = ffi.request.showTray({ id: this.id }) as boolean;
134
- }
135
-
136
- getBounds(): Rectangle {
137
- return ffi.request.getTrayBounds({ id: this.id });
138
- }
139
-
140
- remove() {
141
- console.log("Tray.remove() called for id:", this.id);
142
- const trayId = this.id;
143
- if (trayId) {
144
- ffi.request.removeTray({ id: trayId });
145
- }
146
- this.visible = false;
147
- delete TrayMap[trayId];
148
- this.id = 0;
149
- console.log("Tray removed from TrayMap");
150
- }
151
-
152
- static getById(id: number) {
153
- return TrayMap[id];
154
- }
155
-
156
- static getAll() {
157
- return Object.values(TrayMap);
158
- }
159
-
160
- static removeById(id: number) {
161
- const tray = TrayMap[id];
162
- if (tray) {
163
- tray.remove();
164
- }
165
- }
166
- }
167
-
168
- const menuConfigWithDefaults = (
169
- menu: Array<MenuItemConfig>,
170
- ): Array<MenuItemConfig> => {
171
- return menu.map((item) => {
172
- if (item.type === "divider" || item.type === "separator") {
173
- return { type: "divider" } as const;
174
- } else {
175
- const menuItem = item as NonDividerMenuItem;
176
- // Use shared serialization method
177
- const actionWithDataId = ffi.internal.serializeMenuAction(
178
- menuItem.action || "",
179
- menuItem.data,
180
- );
181
-
182
- return {
183
- label: menuItem.label || "",
184
- type: menuItem.type || "normal",
185
- action: actionWithDataId,
186
- // default enabled to true unless explicitly set to false
187
- enabled: menuItem.enabled === false ? false : true,
188
- checked: Boolean(menuItem.checked),
189
- hidden: Boolean(menuItem.hidden),
190
- tooltip: menuItem.tooltip || undefined,
191
- ...(menuItem.submenu
192
- ? { submenu: menuConfigWithDefaults(menuItem.submenu) }
193
- : {}),
194
- };
195
- }
196
- });
197
- };