electrobun 1.18.4-beta.12 → 1.18.4-beta.18

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 (120) hide show
  1. package/README.md +28 -10
  2. package/bun.lock +13 -0
  3. package/dash.config.ts +36 -9
  4. package/dist/api/browser/global.d.ts +2 -0
  5. package/dist/api/browser/index.ts +51 -22
  6. package/dist/api/browser/webviewtag.ts +16 -7
  7. package/dist/api/browser/wgputag.ts +1 -1
  8. package/dist/api/config/ElectrobunConfig.ts +75 -50
  9. package/dist/api/config/validate.test.ts +16 -10
  10. package/dist/api/config/validate.ts +4 -6
  11. package/dist/api/config/windowsPermissions.ts +24 -0
  12. package/dist/api/preload/.generated/compiled.ts +2 -2
  13. package/dist/api/preload/dragRegions.test.ts +153 -0
  14. package/dist/api/preload/dragRegions.ts +446 -24
  15. package/dist/api/preload/events.test.ts +53 -0
  16. package/dist/api/preload/events.ts +32 -6
  17. package/dist/api/preload/externalDropFocus.test.ts +86 -0
  18. package/dist/api/preload/externalDropFocus.ts +41 -0
  19. package/dist/api/preload/globals.d.ts +1 -0
  20. package/dist/api/preload/index-sandboxed.ts +2 -0
  21. package/dist/api/preload/index.ts +4 -6
  22. package/dist/api/preload/overlaySync.test.ts +50 -0
  23. package/dist/api/preload/overlaySync.ts +2 -0
  24. package/dist/api/preload/webviewTag.ts +67 -16
  25. package/dist/api/preload/webviewTagNavigation.test.ts +23 -0
  26. package/dist/api/preload/webviewTagNavigation.ts +26 -0
  27. package/dist/api/preload/wgpuTag.ts +1 -6
  28. package/dist/api/sdks/main/__tests__/build-config.test.ts +12 -0
  29. package/dist/api/sdks/{bun → main}/core/BrowserView.ts +158 -13
  30. package/dist/api/sdks/{bun → main}/core/BrowserWindow.ts +58 -15
  31. package/dist/api/sdks/main/core/BuildConfig.ts +120 -0
  32. package/dist/api/sdks/{bun → main}/core/GpuWindow.ts +32 -13
  33. package/dist/api/sdks/{bun → main}/core/Updater.ts +39 -19
  34. package/dist/api/sdks/{bun → main}/core/Utils.ts +2 -2
  35. package/dist/api/sdks/main/core/WindowsUpdateTask.test.ts +174 -0
  36. package/dist/api/sdks/main/core/WindowsUpdateTask.ts +111 -0
  37. package/dist/api/sdks/main/entries/app-menu.ts +2 -0
  38. package/dist/api/sdks/main/entries/browser-view.ts +2 -0
  39. package/dist/api/sdks/main/entries/browser-window.ts +2 -0
  40. package/dist/api/sdks/main/entries/build-config.ts +2 -0
  41. package/dist/api/sdks/main/entries/context-menu.ts +2 -0
  42. package/dist/api/sdks/main/entries/events.ts +5 -0
  43. package/dist/api/sdks/main/entries/gpu-window.ts +2 -0
  44. package/dist/api/sdks/main/entries/native.ts +16 -0
  45. package/dist/api/sdks/main/entries/paths.ts +1 -0
  46. package/dist/api/sdks/main/entries/rpc.ts +14 -0
  47. package/dist/api/sdks/main/entries/socket.ts +4 -0
  48. package/dist/api/sdks/main/entries/tray.ts +2 -0
  49. package/dist/api/sdks/main/entries/updater.ts +6 -0
  50. package/dist/api/sdks/main/entries/utils.ts +1 -0
  51. package/dist/api/sdks/main/entries/webgpu.ts +6 -0
  52. package/dist/api/sdks/main/entries/wgpu-view.ts +2 -0
  53. package/dist/api/sdks/{bun → main}/events/windowEvents.ts +2 -0
  54. package/dist/api/sdks/{bun → main}/index.ts +14 -1
  55. package/dist/api/sdks/main/proc/eventBridge.test.ts +40 -0
  56. package/dist/api/sdks/main/proc/eventBridge.ts +43 -0
  57. package/dist/api/sdks/{bun → main}/proc/native.ts +146 -25
  58. package/dist/api/sdks/{bun → main}/webgpuAdapter.ts +50 -35
  59. package/dist/api/sdks/main/webgpuRenderPass.test.ts +77 -0
  60. package/dist/api/sdks/main/webgpuRenderPass.ts +58 -0
  61. package/dist/api/shared/bridge-payload-ownership.test.ts +50 -0
  62. package/dist/api/shared/build-dependencies.ts +2 -2
  63. package/dist/api/shared/bun-version.ts +2 -0
  64. package/dist/api/shared/cef-find-session.test.ts +117 -0
  65. package/dist/api/shared/console-forwarding.test.ts +80 -0
  66. package/dist/api/shared/dialog-paths.test.ts +30 -0
  67. package/dist/api/shared/dialog-paths.ts +12 -0
  68. package/dist/api/shared/linux-abi-release-contract.test.ts +29 -0
  69. package/dist/api/shared/linux-cef-dpi.test.ts +132 -0
  70. package/dist/api/shared/linux-cef-lifecycle.test.ts +195 -0
  71. package/dist/api/shared/linux-desktop-wm-class.test.ts +26 -0
  72. package/dist/api/shared/linux-native-file-dialog.test.ts +40 -0
  73. package/dist/api/shared/linux-tray-contract.test.ts +54 -0
  74. package/dist/api/shared/linux-webkit-automation.test.ts +70 -0
  75. package/dist/api/shared/linux-window-sizing.test.ts +27 -0
  76. package/dist/api/shared/linux-x11-geometry.test.ts +302 -0
  77. package/dist/api/shared/native-compile-flags.test.ts +82 -0
  78. package/dist/api/shared/native-compile-flags.ts +41 -0
  79. package/dist/api/shared/package-exports.test.ts +234 -0
  80. package/dist/api/shared/partition-context.test.ts +38 -0
  81. package/dist/api/shared/published-package-contract.test.ts +133 -0
  82. package/dist/api/shared/rpc.test.ts +117 -0
  83. package/dist/api/shared/rpc.ts +73 -19
  84. package/dist/api/shared/spell-check.test.js +64 -0
  85. package/dist/api/shared/window-visibility.test.ts +42 -0
  86. package/dist/api/shared/windows-cef-lifecycle.test.ts +189 -0
  87. package/dist/api/shared/windows-profile-paths.test.ts +105 -0
  88. package/dist/api/shared/windows-unicode-ui.test.ts +135 -0
  89. package/dist/api/shared/windows-webview-bounds.test.ts +46 -0
  90. package/dist/api/shared/windows-webview-socket-lifecycle.test.ts +36 -0
  91. package/dist/api/shared/windows-webview2-permissions.test.ts +70 -0
  92. package/dist/api/shared/windows-window-shell.test.ts +222 -0
  93. package/dist/go-sdk/callbacks.go +12 -0
  94. package/dist/go-sdk/electrobun.go +72 -13
  95. package/dist/odin-sdk/electrobun/electrobun.odin +115 -9
  96. package/dist/preload-full.js +479 -50
  97. package/dist/preload-sandboxed.js +16 -5
  98. package/dist/rust-sdk/electrobun.rs +70 -0
  99. package/dist/zig-sdk/electrobun.zig +135 -3
  100. package/package.json +38 -3
  101. package/dist/api/sdks/bun/core/BuildConfig.ts +0 -71
  102. package/src/cli/bun.lockb +0 -0
  103. package/src/cli/index.ts +0 -5632
  104. package/src/cli/package-lock.json +0 -81
  105. package/src/cli/package.json +0 -11
  106. /package/dist/api/sdks/{bun → main}/__tests__/ffi-contract.test.ts +0 -0
  107. /package/dist/api/sdks/{bun → main}/core/ApplicationMenu.ts +0 -0
  108. /package/dist/api/sdks/{bun → main}/core/ContextMenu.ts +0 -0
  109. /package/dist/api/sdks/{bun → main}/core/Paths.ts +0 -0
  110. /package/dist/api/sdks/{bun → main}/core/Socket.ts +0 -0
  111. /package/dist/api/sdks/{bun → main}/core/Tray.ts +0 -0
  112. /package/dist/api/sdks/{bun → main}/core/WGPUView.ts +0 -0
  113. /package/dist/api/sdks/{bun → main}/core/menuRoles.ts +0 -0
  114. /package/dist/api/sdks/{bun → main}/events/ApplicationEvents.ts +0 -0
  115. /package/dist/api/sdks/{bun → main}/events/event.ts +0 -0
  116. /package/dist/api/sdks/{bun → main}/events/eventEmitter.ts +0 -0
  117. /package/dist/api/sdks/{bun → main}/events/trayEvents.ts +0 -0
  118. /package/dist/api/sdks/{bun → main}/events/webviewEvents.ts +0 -0
  119. /package/dist/api/sdks/{bun → main}/proc/linux.md +0 -0
  120. /package/dist/api/sdks/{bun → main}/webGPU.ts +0 -0
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <a href="https://electrobun.dev"><img src="https://github.com/blackboardsh/electrobun/assets/75102186/8799b522-0507-45e9-86e3-c3cfded1aa7c" alt="Logo" height=170></a>
2
+ <a href="https://framework.blackboard.sh/electrobun/"><img src="https://github.com/blackboardsh/electrobun/assets/75102186/8799b522-0507-45e9-86e3-c3cfded1aa7c" alt="Logo" height=170></a>
3
3
  </p>
4
4
 
5
5
  <h1 align="center">Electrobun</h1>
@@ -13,28 +13,33 @@
13
13
 
14
14
  ## What is Electrobun?
15
15
 
16
- Electrobun aims to be a complete **solution-in-a-box** for building, updating, and shipping ultra fast, tiny, and cross-platform desktop applications written in Typescript.
17
- Under the hood it uses Cottontail, Electrobun's JSC-based JavaScript runtime, to execute the main process and bundle webview TypeScript. Native bindings are written in ObjC and C++, with several core components written in <a href="https://ziglang.org/">Zig</a>.
16
+ Electrobun aims to be a complete **solution-in-a-box** for building, updating, and shipping fast, compact, cross-platform desktop applications written in TypeScript.
17
+ Hutch is the native build and package-management CLI. Cottontail is Electrobun's JSC-based default JavaScript runtime. Electrobun's platform layer combines Zig, Objective-C, and C++.
18
18
 
19
19
  Visit <a href="https://framework.blackboard.sh/electrobun/">https://framework.blackboard.sh/electrobun/</a> to see api documentation, guides, and more.
20
20
 
21
- You use it via npm.
21
+ Install Hutch globally, then use it to create a project, install the npm package that provides Electrobun's SDKs, and build the application:
22
+
23
+ ```bash
24
+ curl -fsSL https://hutch.blackboard.sh/hutch/install.sh | sh
25
+ hutch electrobun init
26
+ ```
22
27
 
23
28
  Don't miss our:
24
- - self-extracting bundles that use ZSTD compression for more compact distributables as small as 16MB
25
- - zig optimized BSDIFF implementation that lets you ship tiny app updates as small as 4KB
29
+ - self-extracting bundles that use Zstandard compression for compact distributables
30
+ - a Zig-optimized BSDIFF implementation that can produce kilobyte-scale updates
26
31
  - `bundleCEF` flag to bundle and pin Chromium for those that want that tradeoff of consistency over file size
27
32
  - `bundleWGPU` that lets you use Bun Typescript -> WGPU to control a native GPU surface without a webview
28
33
  - Our Three.js and Babylon.js adapters that work directly in the Cottontail main process
29
- - Our `<electrobun-webview>` and `<electrobun-wpgu>` html elements that let you composit proper OOPIFs and native GPU surfaces into your UIs
34
+ - Our `<electrobun-webview>` and `<electrobun-wgpu>` HTML elements that let you composite isolated webviews and native GPU surfaces into your UIs
30
35
  - so much more.
31
36
 
32
37
  **Project Goals**
33
38
 
34
39
  - Write typescript for the main process and webviews without having to think about it.
35
40
  - Isolation between main and webview processes with fast, typed, easy to implement RPC between them.
36
- - Small self-extracting app bundles ~14MB (when using the system webview, most of this is the Cottontail/JSC runtime)
37
- - Even smaller app updates as small as 4KB (using bsdiff it only downloads tiny patches between versions)
41
+ - Small self-extracting app bundles when using the system webview
42
+ - Small updates that use binary patches before falling back to a compressed full download
38
43
  - Provide everything you need in one tightly integrated workflow to start writing code in 5 minutes and distribute in 10.
39
44
 
40
45
  ## Apps Built with Electrobun
@@ -59,6 +64,8 @@ Don't miss our:
59
64
  - [dotlock](https://github.com/tsconfigdotjson/dotlock) - macOS desktop app for managing `.env` files across your projects
60
65
  - [electrobun-pdf](https://github.com/GijungKim/electrobun-pdf) - local-first PDF & DOCX editor for opening, annotating, and exporting documents without leaving your machine
61
66
  - [electrobun-rms](https://github.com/khanhthanhdev/electrobun-rms) - fast Electrobun desktop app template with React, Tailwind CSS, and Vite
67
+ - [FLACK](https://github.com/BLCK-B/FLACK) - local audio player for Windows
68
+ - [gloomberb](https://gloom.sh) - financial terminal for the rest of us
62
69
  - [golb](https://github.com/chrisdadev13/golb) - desktop AI coding workspace built with React, Vite, and Tailwind
63
70
  - [GOG Achievements GUI](https://github.com/timendum/gog-achievements-gui) - desktop app for managing GOG achievements
64
71
  - [groov](https://github.com/laurenzcodes/groov) - desktop audio deck monitor
@@ -142,6 +149,12 @@ On Windows PowerShell:
142
149
 
143
150
  On Ubuntu/Debian based distros: `sudo apt install build-essential cmake pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev`
144
151
 
152
+ Linux applications also require the corresponding GTK 3, WebKitGTK 4.1,
153
+ Ayatana AppIndicator, and librsvg runtime packages on end-user systems. See the
154
+ [cross-platform development guide](./docs/src/content/docs/electrobun/guides/cross-platform-development.mdx#linux)
155
+ for distro-specific install commands. The launcher reports the exact missing
156
+ shared library when these dependencies are unavailable.
157
+
145
158
  ### First-time Setup
146
159
 
147
160
  ```bash
@@ -164,6 +177,11 @@ hutch dev
164
177
  hutch dev:clean
165
178
  ```
166
179
 
180
+ The native build generates `package/src/native/compile_flags.txt` from the
181
+ compiler flags resolved for the current machine. clangd-compatible editors
182
+ discover it automatically; rerun the build after changing native dependencies
183
+ or system toolchains.
184
+
167
185
  With sibling `jsc`, `cottontail`, `dash-cloud`, and `electrobun` checkouts, use
168
186
  one command to build only changed native layers and run Kitchen with the local
169
187
  stack:
@@ -194,6 +212,6 @@ All commands are run from the `/package` directory:
194
212
  |---|---|
195
213
  | macOS 14+ | Official |
196
214
  | Windows 11+ | Official |
197
- | Ubuntu 22.04+ | Official |
215
+ | Ubuntu 24.04+ | Official |
198
216
  | Other Linux distros (gtk3, webkit2gtk-4.1) | Community |
199
217
  | Raspberry Pi | Unofficial fork: [kortexa-ai/electrobun (linux-wpe)](https://github.com/kortexa-ai/electrobun/tree/kortexa/linux-wpe) — follow the author [@francip](https://x.com/francip/status/2050149256053539059?s=20) |
package/bun.lock CHANGED
@@ -7,6 +7,7 @@
7
7
  "dependencies": {
8
8
  "@babylonjs/core": "^7.45.0",
9
9
  "@types/bun": "^1.3.8",
10
+ "@types/three": "^0.165.0",
10
11
  "png-to-ico": "^2.1.8",
11
12
  "proxy-agent": "^6.5.0",
12
13
  "rcedit": "^4.0.1",
@@ -24,10 +25,18 @@
24
25
 
25
26
  "@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="],
26
27
 
28
+ "@tweenjs/tween.js": ["@tweenjs/tween.js@23.1.3", "", {}, "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA=="],
29
+
27
30
  "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
28
31
 
29
32
  "@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="],
30
33
 
34
+ "@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="],
35
+
36
+ "@types/three": ["@types/three@0.165.0", "", { "dependencies": { "@tweenjs/tween.js": "~23.1.1", "@types/stats.js": "*", "@types/webxr": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.18.1" } }, "sha512-AJK8JZAFNBF0kBXiAIl5pggYlzAGGA8geVYQXAcPCEDRbyA+oEjkpUBcJJrtNz6IiALwzGexFJGZG2yV3WsYBw=="],
37
+
38
+ "@types/webxr": ["@types/webxr@0.5.24", "", {}, "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg=="],
39
+
31
40
  "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
32
41
 
33
42
  "ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="],
@@ -54,6 +63,8 @@
54
63
 
55
64
  "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
56
65
 
66
+ "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="],
67
+
57
68
  "get-uri": ["get-uri@6.0.5", "", { "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4" } }, "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg=="],
58
69
 
59
70
  "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
@@ -70,6 +81,8 @@
70
81
 
71
82
  "lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
72
83
 
84
+ "meshoptimizer": ["meshoptimizer@0.18.1", "", {}, "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw=="],
85
+
73
86
  "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
74
87
 
75
88
  "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
package/dash.config.ts CHANGED
@@ -1,13 +1,14 @@
1
- // @dash cli=0.3.1 cottontail=0.2.3
1
+ // @dash cli=0.5.0-canary.8 cottontail=0.2.3
2
2
  export default {
3
3
  scripts: {
4
- start: "hutch src/sdks/bun/index.ts",
4
+ start: "hutch src/sdks/main/index.ts",
5
5
  "check-zig-version": "vendors/zig/zig version",
6
6
  "check-rust-version": "vendors/rust/bin/rustc --version",
7
7
  "build:dev": "hutch build.ts",
8
8
  "build:local": "scripts/build-local.js",
9
9
  "build:release": "hutch build.ts --release",
10
10
  dev: "scripts/dev.ts",
11
+ "dev:matrix": "scripts/dev-matrix.ts",
11
12
  "dev:test": "scripts/dev.test.ts",
12
13
  "dev:clean": "cd ../kitchen && rm -rf node_modules vendors/cef && cd ../package && hutch dev",
13
14
  "dev:canary": "hutch install && hutch build:release && cd ../kitchen && hutch install && hutch electrobun build --env=canary",
@@ -15,14 +16,40 @@ export default {
15
16
  "build:docs:release": "cd ../docs && hutch run build",
16
17
  "npm:publish": "hutch build:release && npm publish",
17
18
  "npm:publish:beta": "hutch build:release && npm publish --tag beta",
18
- typecheck: "./node_modules/.bin/tsc --noEmit && cd ../kitchen && ./node_modules/.bin/tsc --noEmit",
19
- "push:beta": "hutch typecheck && node scripts/push-version.js beta",
20
- "push:patch": "hutch typecheck && node scripts/push-version.js patch",
21
- "push:minor": "hutch typecheck && node scripts/push-version.js minor",
22
- "push:major": "hutch typecheck && node scripts/push-version.js major",
23
- "push:stable": "hutch typecheck && node scripts/push-version.js stable",
19
+ typecheck:
20
+ "node node_modules/typescript/bin/tsc --noEmit && cd ../kitchen && node node_modules/typescript/bin/tsc --noEmit",
21
+ "check:release": "hutch typecheck && hutch test:templates && hutch test:template-publisher && hutch test:signing && hutch test:deployment-target && hutch test:linux-abi && hutch test:linux-extractor && hutch test:npm-bootstrap && hutch test:release-notes",
22
+ "push:beta": "hutch check:release && node scripts/push-version.js beta",
23
+ "push:patch": "hutch check:release && node scripts/push-version.js patch",
24
+ "push:minor": "hutch check:release && node scripts/push-version.js minor",
25
+ "push:major": "hutch check:release && node scripts/push-version.js major",
26
+ "push:stable": "hutch check:release && node scripts/push-version.js stable",
24
27
  "build:push:artifacts": "node scripts/build-and-upload-artifacts.js",
25
- "test:unit": "hutch test src/shared src/sdks/bun src/config",
28
+ "test:dialog-paths-native": "hutch scripts/test-dialog-paths-native.js",
29
+ "test:linux-cef-idle": "node scripts/test-linux-cef-idle.js",
30
+ "test:linux-dpi-native": "hutch scripts/test-linux-dpi-native.js",
31
+ "test:linux-x11-geometry-native":
32
+ "hutch scripts/test-linux-x11-geometry-native.js",
33
+ "test:views-url-native": "hutch scripts/test-views-url-native.js",
34
+ "test:windows-ui-native": "hutch scripts/test-windows-ui-native.js",
35
+ "test:windows-ui-native-integration":
36
+ "hutch scripts/test-windows-ui-native.js --require-native-wrapper",
37
+ "test:unit": "node scripts/run-cottontail-test.js src/shared src/sdks/main src/config src/preload && hutch test:dialog-paths-native && hutch test:linux-dpi-native && hutch test:linux-x11-geometry-native && hutch test:views-url-native && hutch test:webview2-permissions && hutch test:windows-ui-native",
38
+ "test:linux-native-dialog":
39
+ "node scripts/run-cottontail-test.js src/shared/linux-native-file-dialog.test.ts && scripts/test-linux-native-file-dialog.sh",
40
+ "test:cef-debug": "scripts/test-cef-remote-debugging.ts",
41
+ "test:webview2-permissions": "scripts/test-webview2-permissions.ts",
42
+ "test:macos-inspector-layout": "scripts/test-macos-inspector-layout.sh",
43
+ "test:templates": "node scripts/run-cottontail-test.js ../templates/template-manifests.test.ts",
44
+ "test:template-publisher": "node --test ../scripts/publish-templates.test.mjs",
45
+ "test:signing": "node scripts/run-cottontail-test.js scripts/verify-macho-code-signing.test.ts",
46
+ "test:deployment-target": "node scripts/run-cottontail-test.js scripts/verify-macho-deployment-target.test.ts",
47
+ "test:linux-abi": "node scripts/run-cottontail-test.js scripts/verify-linux-elf-abi.test.ts",
48
+ "test:linux-extractor": "node scripts/test-linux-adjacent-extractor.mjs",
49
+ "test:npm-bootstrap": "node scripts/run-cottontail-test.js bin/npm-bootstrap-retirement.test.ts",
50
+ "test:release-notes": "node scripts/release-notes-contract.test.mjs",
51
+ "test:spell-check": "node --test src/shared/spell-check.test.js",
52
+ "test:macos-spell-check": "scripts/test-macos-spell-check.sh",
26
53
  "bump-cef": "hutch scripts/update-cef-version.ts",
27
54
  },
28
55
  };
@@ -19,6 +19,7 @@ interface MessageHandler {
19
19
 
20
20
  declare global {
21
21
  interface Window {
22
+ __electrobunPlatform: "linux" | "macos" | "windows";
22
23
  __electrobunWebviewId: number;
23
24
  __electrobunWindowId: number;
24
25
  __electrobunRpcSocketPort: number;
@@ -31,6 +32,7 @@ declare global {
31
32
  __electrobunInternalBridge?: MessageHandler;
32
33
  __electrobunHostBridge?: MessageHandler;
33
34
  __electrobunBunBridge?: MessageHandler;
35
+ __electrobunSendToHost: (message: unknown) => void;
34
36
  }
35
37
  }
36
38
 
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  type RPCSchema,
3
3
  type RPCTransport,
4
+ type RPCRequestOptions,
4
5
  type ElectrobunRPCSchema,
5
6
  type ElectrobunRPCConfig,
6
7
  type RPCWithTransport,
@@ -18,12 +19,17 @@ const WEBVIEW_ID = window.__electrobunWebviewId;
18
19
  const HOST_SOCKET_PORT =
19
20
  window.__electrobunHostSocketPort ?? window.__electrobunRpcSocketPort;
20
21
 
22
+ type QueuedHostMessage = {
23
+ message: string;
24
+ markSent: () => void;
25
+ };
26
+
21
27
  class Electroview<T extends RPCWithTransport> {
22
28
  hostSocket?: WebSocket;
23
29
  hostSocketCanSend = false;
24
- pendingHostSocketMessages: string[] = [];
30
+ pendingHostSocketMessages: QueuedHostMessage[] = [];
25
31
  flushingHostSocketMessages = false;
26
- hostSocketSendQueue: string[] = [];
32
+ hostSocketSendQueue: QueuedHostMessage[] = [];
27
33
  flushingHostSocketSendQueue = false;
28
34
  // user's custom rpc browser <-> bun
29
35
  rpc?: T;
@@ -119,7 +125,8 @@ class Electroview<T extends RPCWithTransport> {
119
125
 
120
126
  socket.addEventListener("close", (_event) => {
121
127
  this.hostSocketCanSend = false;
122
- this.pendingHostSocketMessages = [];
128
+ this.flushHostMessagesViaFallback(this.pendingHostSocketMessages);
129
+ this.flushHostMessagesViaFallback(this.hostSocketSendQueue);
123
130
  // console.log("Socket closed:", event);
124
131
  });
125
132
  }
@@ -130,7 +137,7 @@ class Electroview<T extends RPCWithTransport> {
130
137
  send(message: unknown) {
131
138
  try {
132
139
  const messageString = JSON.stringify(message);
133
- that.sendMessageToHost(messageString);
140
+ return that.sendMessageToHost(messageString);
134
141
  } catch (error) {
135
142
  console.error("host: failed to serialize message to webview", error);
136
143
  }
@@ -141,20 +148,24 @@ class Electroview<T extends RPCWithTransport> {
141
148
  };
142
149
  }
143
150
 
144
- async sendMessageToHost(msg: string) {
145
- if (this.canSendToHostSocket()) {
146
- this.hostSocketSendQueue.push(msg);
147
- void this.flushHostSocketSendQueue();
148
- return;
149
- }
151
+ sendMessageToHost(msg: string): Promise<void> {
152
+ return new Promise((markSent) => {
153
+ const queuedMessage = { message: msg, markSent };
150
154
 
151
- if (this.hostSocket?.readyState === WebSocket.CONNECTING) {
152
- this.pendingHostSocketMessages.push(msg);
153
- return;
154
- }
155
+ if (this.canSendToHostSocket()) {
156
+ this.hostSocketSendQueue.push(queuedMessage);
157
+ void this.flushHostSocketSendQueue();
158
+ return;
159
+ }
155
160
 
156
- // if socket's are unavailable, fallback to postMessage
157
- window.__electrobunHostBridge?.postMessage(msg);
161
+ if (this.hostSocket?.readyState === WebSocket.CONNECTING) {
162
+ this.pendingHostSocketMessages.push(queuedMessage);
163
+ return;
164
+ }
165
+
166
+ // If sockets are unavailable, hand the packet to the native bridge.
167
+ this.sendMessageToHostViaFallback(queuedMessage);
168
+ });
158
169
  }
159
170
 
160
171
  canSendToHostSocket() {
@@ -174,7 +185,6 @@ class Electroview<T extends RPCWithTransport> {
174
185
  this.hostSocket!.send(msg);
175
186
  return true;
176
187
  }
177
- await new Promise((resolve) => setTimeout(resolve, 0));
178
188
  const { encryptedData, iv, tag } =
179
189
  await window.__electrobun_encrypt(msg);
180
190
 
@@ -192,6 +202,22 @@ class Electroview<T extends RPCWithTransport> {
192
202
  }
193
203
  }
194
204
 
205
+ sendMessageToHostViaFallback(queuedMessage: QueuedHostMessage) {
206
+ try {
207
+ window.__electrobunHostBridge?.postMessage(queuedMessage.message);
208
+ } catch (error) {
209
+ console.error("Error sending message to host via native bridge:", error);
210
+ } finally {
211
+ queuedMessage.markSent();
212
+ }
213
+ }
214
+
215
+ flushHostMessagesViaFallback(queue: QueuedHostMessage[]) {
216
+ while (queue.length > 0) {
217
+ this.sendMessageToHostViaFallback(queue.shift()!);
218
+ }
219
+ }
220
+
195
221
  async flushHostSocketSendQueue() {
196
222
  if (this.flushingHostSocketSendQueue) {
197
223
  return;
@@ -203,10 +229,12 @@ class Electroview<T extends RPCWithTransport> {
203
229
  this.hostSocketSendQueue.length > 0 &&
204
230
  this.canSendToHostSocket()
205
231
  ) {
206
- const message = this.hostSocketSendQueue[0]!;
232
+ const queuedMessage = this.hostSocketSendQueue[0]!;
207
233
  this.hostSocketSendQueue.shift();
208
- if (!(await this.sendMessageToHostSocket(message))) {
209
- window.__electrobunHostBridge?.postMessage(message);
234
+ if (!(await this.sendMessageToHostSocket(queuedMessage.message))) {
235
+ this.sendMessageToHostViaFallback(queuedMessage);
236
+ } else {
237
+ queuedMessage.markSent();
210
238
  }
211
239
  }
212
240
  } finally {
@@ -222,8 +250,8 @@ class Electroview<T extends RPCWithTransport> {
222
250
  this.flushingHostSocketMessages = true;
223
251
  try {
224
252
  while (this.pendingHostSocketMessages.length > 0) {
225
- const message = this.pendingHostSocketMessages.shift()!;
226
- this.hostSocketSendQueue.push(message);
253
+ const queuedMessage = this.pendingHostSocketMessages.shift()!;
254
+ this.hostSocketSendQueue.push(queuedMessage);
227
255
  }
228
256
  await this.flushHostSocketSendQueue();
229
257
  } finally {
@@ -293,6 +321,7 @@ class Electroview<T extends RPCWithTransport> {
293
321
 
294
322
  export {
295
323
  type RPCSchema,
324
+ type RPCRequestOptions,
296
325
  type ElectrobunRPCSchema,
297
326
  type ElectrobunRPCConfig,
298
327
  createRPC,
@@ -1,12 +1,20 @@
1
1
  import "./global.d.ts";
2
2
 
3
3
  type WebviewEventTypes =
4
+ | "will-navigate"
4
5
  | "did-navigate"
5
6
  | "did-navigate-in-page"
6
7
  | "did-commit-navigation"
7
8
  | "dom-ready"
8
9
  | "host-message"
9
- | "new-window-open";
10
+ | "new-window-open"
11
+ | "download-started"
12
+ | "download-progress"
13
+ | "download-completed"
14
+ | "download-failed"
15
+ | "load-started"
16
+ | "load-committed"
17
+ | "load-finished";
10
18
 
11
19
  /**
12
20
  * Interface representing an <electrobun-webview> custom element.
@@ -19,13 +27,13 @@ type WebviewEventTypes =
19
27
  */
20
28
  interface WebviewTagElement extends HTMLElement {
21
29
  // Properties
22
- webviewId?: number;
30
+ webviewId: number | null;
23
31
  maskSelectors: Set<string>;
24
32
  transparent: boolean;
25
33
  passthroughEnabled: boolean;
34
+ spellCheckEnabled: boolean;
26
35
  hidden: boolean;
27
- hiddenMirrorMode: boolean;
28
- partition: string | null;
36
+ readonly sandbox: boolean;
29
37
 
30
38
  // Attribute-backed properties (getters/setters)
31
39
  src: string | null;
@@ -45,11 +53,12 @@ interface WebviewTagElement extends HTMLElement {
45
53
  reload(): void;
46
54
  loadURL(url: string): void;
47
55
  loadHTML(html: string): void;
56
+ setSpellCheck(enabled: boolean): Promise<boolean>;
48
57
 
49
58
  // Visibility and interaction
50
- toggleTransparent(transparent?: boolean, bypassState?: boolean): void;
51
- togglePassthrough(enablePassthrough?: boolean, bypassState?: boolean): void;
52
- toggleHidden(hidden?: boolean, bypassState?: boolean): void;
59
+ toggleTransparent(transparent?: boolean): void;
60
+ togglePassthrough(enablePassthrough?: boolean): void;
61
+ toggleHidden(hidden?: boolean): void;
53
62
 
54
63
  // Events - listener receives a CustomEvent with detail property
55
64
  on(event: WebviewEventTypes, listener: (event: CustomEvent) => void): void;
@@ -12,7 +12,7 @@ type WgpuEventTypes = "ready";
12
12
  */
13
13
  interface WgpuTagElement extends HTMLElement {
14
14
  // Properties
15
- wgpuViewId?: number;
15
+ wgpuViewId: number | null;
16
16
  transparent: boolean;
17
17
  passthroughEnabled: boolean;
18
18
  hidden: boolean;
@@ -3,15 +3,19 @@
3
3
  * Used in electrobun.config.ts files
4
4
  */
5
5
 
6
+ import type { WindowsWebView2Permission } from "./windowsPermissions";
7
+
6
8
  type BundlerOptions = {
7
9
  external?: string[];
8
10
  define?: Record<string, string>;
9
- loader?: Record<string, string>;
11
+ alias?: Record<string, string>;
10
12
  minify?: boolean;
11
13
  sourcemap?: boolean | "inline" | "external" | "linked";
12
- splitting?: boolean;
13
- plugins?: unknown[];
14
- [key: string]: unknown;
14
+ target?: string | string[];
15
+ };
16
+
17
+ type ViewBundlerOptions = BundlerOptions & {
18
+ format?: "esm" | "cjs" | "iife";
15
19
  };
16
20
 
17
21
  type CarrotFileActivatorConfig = {
@@ -137,6 +141,7 @@ export interface ElectrobunConfig {
137
141
  build?: {
138
142
  /**
139
143
  * Main process implementation to build and package.
144
+ * - "bun": bundle and run the Bun main process entrypoint
140
145
  * - "cottontail": bundle and run the Cottontail main process entrypoint
141
146
  * - "zig": compile and run the Zig main process entrypoint
142
147
  * - "rust": compile and run the Rust main process entrypoint
@@ -144,7 +149,19 @@ export interface ElectrobunConfig {
144
149
  * - "odin": compile and run the Odin main process entrypoint
145
150
  * @default "cottontail"
146
151
  */
147
- mainProcess?: "cottontail" | "zig" | "rust" | "go" | "odin";
152
+ mainProcess?: "bun" | "cottontail" | "zig" | "rust" | "go" | "odin";
153
+
154
+ /**
155
+ * Bun main process build configuration.
156
+ * Used when `build.mainProcess` is set to `"bun"`.
157
+ */
158
+ bun?: {
159
+ /**
160
+ * Entry point for the main Bun process
161
+ * @default "src/bun/index.ts"
162
+ */
163
+ entrypoint?: string;
164
+ } & BundlerOptions;
148
165
 
149
166
  /**
150
167
  * Cottontail main process build configuration.
@@ -213,8 +230,8 @@ export interface ElectrobunConfig {
213
230
 
214
231
  /**
215
232
  * Browser view build configurations.
216
- * Each view accepts bundler options (plugins, sourcemap, minify, define, etc.)
217
- * in addition to the entrypoint.
233
+ * Each view accepts the supported bundler options in addition to the
234
+ * entrypoint.
218
235
  */
219
236
  views?: {
220
237
  [viewName: string]: {
@@ -222,7 +239,7 @@ export interface ElectrobunConfig {
222
239
  * Entry point for this view's TypeScript code
223
240
  */
224
241
  entrypoint: string;
225
- } & BundlerOptions;
242
+ } & ViewBundlerOptions;
226
243
  };
227
244
 
228
245
  /**
@@ -244,47 +261,6 @@ export interface ElectrobunConfig {
244
261
  */
245
262
  artifactFolder?: string;
246
263
 
247
- /**
248
- * Build targets to compile for
249
- * Can be "current", "all", or comma-separated list like "macos-arm64,win-x64"
250
- */
251
- targets?: string;
252
-
253
- /**
254
- * Enable ASAR archive packaging for bundled assets
255
- * When enabled, all files in the Resources folder will be packed into an app.asar archive
256
- * @default false
257
- */
258
- useAsar?: boolean;
259
-
260
- /**
261
- * Glob patterns for files to exclude from ASAR packing (extract to app.asar.unpacked)
262
- * Useful for native modules or executables that need to be accessible as regular files
263
- * @default ["*.node", "*.dll", "*.dylib", "*.so"]
264
- */
265
- asarUnpack?: string[];
266
-
267
- /**
268
- * Override the CEF (Chromium Embedded Framework) version.
269
- * Format: "CEF_VERSION+chromium-CHROMIUM_VERSION"
270
- * Example: "144.0.11+ge135be2+chromium-144.0.7559.97"
271
- *
272
- * Check the electrobun-cef-compat compatibility matrix for tested combinations
273
- * before overriding. Using an untested version may cause runtime issues.
274
- * @default Uses the version bundled with this Electrobun release
275
- */
276
- cefVersion?: string;
277
-
278
- /**
279
- * Override the Dawn (WebGPU) version.
280
- * Format: semver string (e.g., "0.2.3") or tag (e.g., "v0.2.3-beta.0")
281
- *
282
- * This downloads the specified electrobun-dawn release and uses it
283
- * instead of the latest release.
284
- * @default Uses the latest electrobun-dawn release
285
- */
286
- wgpuVersion?: string;
287
-
288
264
  /**
289
265
  * Additional file or directory paths to watch for changes during `electrobun dev --watch`.
290
266
  * Paths are relative to the project root.
@@ -364,6 +340,10 @@ export interface ElectrobunConfig {
364
340
  * - `"value"` — add a flag with a value
365
341
  * - `false` — remove a default flag set by Electrobun
366
342
  *
343
+ * CEF remote debugging is automatic for dev builds and disabled by
344
+ * default for packaged builds. Set `"remote-debugging-port"` to a
345
+ * string port to opt in, or `false` to disable it explicitly.
346
+ *
367
347
  * @example
368
348
  * ```typescript
369
349
  * chromiumFlags: {
@@ -423,6 +403,10 @@ export interface ElectrobunConfig {
423
403
  * - `"value"` — add a flag with a value
424
404
  * - `false` — remove a default flag set by Electrobun
425
405
  *
406
+ * CEF remote debugging is automatic for dev builds and disabled by
407
+ * default for packaged builds. Set `"remote-debugging-port"` to a
408
+ * string port to opt in, or `false` to disable it explicitly.
409
+ *
426
410
  * @example
427
411
  * ```typescript
428
412
  * chromiumFlags: {
@@ -434,7 +418,19 @@ export interface ElectrobunConfig {
434
418
  chromiumFlags?: Record<string, string | boolean>;
435
419
 
436
420
  /**
437
- * Path to application icon (.ico format)
421
+ * WebView2 permissions to grant automatically without showing a prompt.
422
+ * This applies to every origin loaded in a native Windows webview, so only
423
+ * enable permissions that the application intentionally delegates to its
424
+ * web content. This option does not affect CEF webviews.
425
+ *
426
+ * @example ["camera", "microphone"]
427
+ * @default []
428
+ */
429
+ autoGrantPermissions?: WindowsWebView2Permission[];
430
+
431
+ /**
432
+ * Path to an application icon in ICO or PNG format. PNG input is
433
+ * converted to ICO by Hutch.
438
434
  * Used for the installer/extractor wrapper, desktop shortcuts, and taskbar
439
435
  * Should include multiple sizes (16x16, 32x32, 48x48, 256x256) for best results
440
436
  * @example "assets/icon.ico"
@@ -465,6 +461,31 @@ export interface ElectrobunConfig {
465
461
  */
466
462
  defaultRenderer?: "native" | "cef";
467
463
 
464
+ /**
465
+ * Emit an expanded Flatpak-builder recipe alongside the normal Linux
466
+ * artifacts. This is an opt-in packaging MVP: Hutch writes a manifest
467
+ * and `/app` payload but does not invoke `flatpak-builder`.
468
+ */
469
+ flatpak?: {
470
+ /** Enable Flatpak recipe generation. @default false */
471
+ enabled: boolean;
472
+
473
+ /** Output directory relative to `build.artifactFolder`. @default "flatpak" */
474
+ outputPath?: string;
475
+
476
+ /** Flatpak runtime identifier. @default "org.freedesktop.Platform" */
477
+ runtime?: string;
478
+
479
+ /** Flatpak runtime branch. @default "25.08" */
480
+ runtimeVersion?: string;
481
+
482
+ /** Flatpak SDK identifier. @default "org.freedesktop.Sdk" */
483
+ sdk?: string;
484
+
485
+ /** Override the manifest's default sandbox finish arguments. */
486
+ finishArgs?: string[];
487
+ };
488
+
468
489
  /**
469
490
  * Custom Chromium command-line flags to pass to CEF during initialization.
470
491
  * Keys are flag names without the "--" prefix.
@@ -472,6 +493,10 @@ export interface ElectrobunConfig {
472
493
  * - `"value"` — add a flag with a value
473
494
  * - `false` — remove a default flag set by Electrobun
474
495
  *
496
+ * CEF remote debugging is automatic for dev builds and disabled by
497
+ * default for packaged builds. Set `"remote-debugging-port"` to a
498
+ * string port to opt in, or `false` to disable it explicitly.
499
+ *
475
500
  * @example
476
501
  * ```typescript
477
502
  * chromiumFlags: {