electrobun 0.0.2 → 0.0.3

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 (72) hide show
  1. package/.colab.json +1 -0
  2. package/README.md +14 -12
  3. package/bun.lockb +0 -0
  4. package/dist/bsdiff +0 -0
  5. package/dist/bspatch +0 -0
  6. package/dist/webview +0 -0
  7. package/docs-old/architecture.md +46 -0
  8. package/documentation/README.md +41 -0
  9. package/documentation/babel.config.js +3 -0
  10. package/documentation/blog/2024-08-20-electrobun.md +22 -0
  11. package/documentation/blog/authors.yml +8 -0
  12. package/documentation/blog/tags.yml +0 -0
  13. package/documentation/docs/apis/Application Icons.md +9 -0
  14. package/documentation/docs/apis/Bundled Assets.md +95 -0
  15. package/documentation/docs/apis/browser/DraggableRegions.md +36 -0
  16. package/documentation/docs/apis/browser/Electrobun Webview Tag.md +200 -0
  17. package/documentation/docs/apis/browser/Electroview Class.md +158 -0
  18. package/documentation/docs/apis/browser/GlobalProperties.md +11 -0
  19. package/documentation/docs/apis/browser/index.md +25 -0
  20. package/documentation/docs/apis/bun/ApplicationMenu.md +141 -0
  21. package/documentation/docs/apis/bun/BrowserView.md +513 -0
  22. package/documentation/docs/apis/bun/BrowserWindow.md +423 -0
  23. package/documentation/docs/apis/bun/ContextMenu.md +50 -0
  24. package/documentation/docs/apis/bun/Events.md +50 -0
  25. package/documentation/docs/apis/bun/PATHS.md +17 -0
  26. package/documentation/docs/apis/bun/Tray.md +115 -0
  27. package/documentation/docs/apis/bun/Updater.md +74 -0
  28. package/documentation/docs/apis/bun/Utils.md +51 -0
  29. package/documentation/docs/apis/bun/index.md +26 -0
  30. package/documentation/docs/apis/cli/Electrobun.config.md +97 -0
  31. package/documentation/docs/apis/cli/cli args.md +76 -0
  32. package/documentation/docs/guides/Architecture/Events.md +19 -0
  33. package/documentation/docs/guides/Architecture/IPC and Isolation.md +20 -0
  34. package/documentation/docs/guides/Architecture/Overview.md +140 -0
  35. package/documentation/docs/guides/Architecture/Updates.md +7 -0
  36. package/documentation/docs/guides/Architecture/Webview Tag.md +5 -0
  37. package/documentation/docs/guides/Compatability.md +8 -0
  38. package/documentation/docs/guides/Getting Started/Creating UI.md +147 -0
  39. package/documentation/docs/guides/Getting Started/Distributing.md +116 -0
  40. package/documentation/docs/guides/Getting Started/Getting Started.md +7 -0
  41. package/documentation/docs/guides/Getting Started/Hello World.md +93 -0
  42. package/documentation/docs/guides/Getting Started/What is Electrobun.md +39 -0
  43. package/documentation/docs/guides/Guides/Build UI with React +0 -0
  44. package/documentation/docs/guides/Guides/Build UI with Solidjs +0 -0
  45. package/documentation/docs/guides/Guides/Build a Web Browser +0 -0
  46. package/documentation/docs/guides/Guides/Bun <-> Browser RPC +0 -0
  47. package/documentation/docs/guides/Guides/Using Tailwind +0 -0
  48. package/documentation/docusaurus.config.ts +153 -0
  49. package/documentation/package-lock.json +14530 -0
  50. package/documentation/package.json +47 -0
  51. package/documentation/sidebars.ts +32 -0
  52. package/documentation/src/components/HomepageFeatures/index.tsx +70 -0
  53. package/documentation/src/components/HomepageFeatures/styles.module.css +11 -0
  54. package/documentation/src/css/custom.css +30 -0
  55. package/documentation/src/pages/index.module.css +23 -0
  56. package/documentation/src/pages/index.tsx +137 -0
  57. package/documentation/static/.nojekyll +0 -0
  58. package/documentation/static/img/electrobun-logo-256.png +0 -0
  59. package/documentation/static/img/electrobun-logo-32.png +0 -0
  60. package/documentation/tsconfig.json +7 -0
  61. package/package.json +11 -6
  62. package/src/browser/index.ts +2 -2
  63. package/src/bun/core/BrowserView.ts +14 -1
  64. package/src/cli/build/electrobun +0 -0
  65. package/src/cli/index.ts +3 -1
  66. package/docs/architecture.md +0 -84
  67. /package/{docs → docs-old}/api/bun-api.md +0 -0
  68. /package/{docs → docs-old}/api/view-api.md +0 -0
  69. /package/{docs → docs-old}/electrobun-config.md +0 -0
  70. /package/{docs → docs-old}/getting-started.md +0 -0
  71. /package/{docs → docs-old}/node_modules/.cache/webpack/client-development-en/0.pack +0 -0
  72. /package/{docs → docs-old}/node_modules/.cache/webpack/client-development-en/index.pack +0 -0
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "docs",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "docusaurus": "docusaurus",
7
+ "start": "docusaurus start",
8
+ "build": "docusaurus build",
9
+ "swizzle": "docusaurus swizzle",
10
+ "deploy": "docusaurus deploy",
11
+ "clear": "docusaurus clear",
12
+ "serve": "docusaurus serve",
13
+ "write-translations": "docusaurus write-translations",
14
+ "write-heading-ids": "docusaurus write-heading-ids",
15
+ "typecheck": "tsc"
16
+ },
17
+ "dependencies": {
18
+ "@docusaurus/core": "3.5.1",
19
+ "@docusaurus/preset-classic": "3.5.1",
20
+ "@mdx-js/react": "^3.0.0",
21
+ "clsx": "^2.0.0",
22
+ "prism-react-renderer": "^2.3.0",
23
+ "react": "^18.0.0",
24
+ "react-dom": "^18.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@docusaurus/module-type-aliases": "3.5.1",
28
+ "@docusaurus/tsconfig": "3.5.1",
29
+ "@docusaurus/types": "3.5.1",
30
+ "typescript": "~5.5.2"
31
+ },
32
+ "browserslist": {
33
+ "production": [
34
+ ">0.5%",
35
+ "not dead",
36
+ "not op_mini all"
37
+ ],
38
+ "development": [
39
+ "last 3 chrome version",
40
+ "last 3 firefox version",
41
+ "last 5 safari version"
42
+ ]
43
+ },
44
+ "engines": {
45
+ "node": ">=18.0"
46
+ }
47
+ }
@@ -0,0 +1,32 @@
1
+ import type { SidebarsConfig } from "@docusaurus/plugin-content-docs";
2
+
3
+ /**
4
+ * Creating a sidebar enables you to:
5
+ - create an ordered group of docs
6
+ - render a sidebar for each doc of that group
7
+ - provide next/previous navigation
8
+
9
+ The sidebars can be generated from the filesystem, or explicitly defined here.
10
+
11
+ Create as many sidebars as you want.
12
+ */
13
+ const sidebars: SidebarsConfig = {
14
+ // By default, Docusaurus generates a sidebar from the docs folder structure
15
+ guidesSidebar: [{ type: "autogenerated", dirName: "guides" }],
16
+ apiSidebar: [{ type: "autogenerated", dirName: "apis" }],
17
+
18
+ // But you can create a sidebar manually
19
+ /*
20
+ tutorialSidebar: [
21
+ 'intro',
22
+ 'hello',
23
+ {
24
+ type: 'category',
25
+ label: 'Tutorial',
26
+ items: ['tutorial-basics/create-a-document'],
27
+ },
28
+ ],
29
+ */
30
+ };
31
+
32
+ export default sidebars;
@@ -0,0 +1,70 @@
1
+ import clsx from 'clsx';
2
+ import Heading from '@theme/Heading';
3
+ import styles from './styles.module.css';
4
+
5
+ type FeatureItem = {
6
+ title: string;
7
+ Svg: React.ComponentType<React.ComponentProps<'svg'>>;
8
+ description: JSX.Element;
9
+ };
10
+
11
+ const FeatureList: FeatureItem[] = [
12
+ {
13
+ title: 'Easy to Use',
14
+ Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
15
+ description: (
16
+ <>
17
+ Docusaurus was designed from the ground up to be easily installed and
18
+ used to get your website up and running quickly.
19
+ </>
20
+ ),
21
+ },
22
+ {
23
+ title: 'Focus on What Matters',
24
+ Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
25
+ description: (
26
+ <>
27
+ Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go
28
+ ahead and move your docs into the <code>docs</code> directory.
29
+ </>
30
+ ),
31
+ },
32
+ {
33
+ title: 'Powered by React',
34
+ Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
35
+ description: (
36
+ <>
37
+ Extend or customize your website layout by reusing React. Docusaurus can
38
+ be extended while reusing the same header and footer.
39
+ </>
40
+ ),
41
+ },
42
+ ];
43
+
44
+ function Feature({title, Svg, description}: FeatureItem) {
45
+ return (
46
+ <div className={clsx('col col--4')}>
47
+ <div className="text--center">
48
+ <Svg className={styles.featureSvg} role="img" />
49
+ </div>
50
+ <div className="text--center padding-horiz--md">
51
+ <Heading as="h3">{title}</Heading>
52
+ <p>{description}</p>
53
+ </div>
54
+ </div>
55
+ );
56
+ }
57
+
58
+ export default function HomepageFeatures(): JSX.Element {
59
+ return (
60
+ <section className={styles.features}>
61
+ <div className="container">
62
+ <div className="row">
63
+ {FeatureList.map((props, idx) => (
64
+ <Feature key={idx} {...props} />
65
+ ))}
66
+ </div>
67
+ </div>
68
+ </section>
69
+ );
70
+ }
@@ -0,0 +1,11 @@
1
+ .features {
2
+ display: flex;
3
+ align-items: center;
4
+ padding: 2rem 0;
5
+ width: 100%;
6
+ }
7
+
8
+ .featureSvg {
9
+ height: 200px;
10
+ width: 200px;
11
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Any CSS included here will be global. The classic template
3
+ * bundles Infima by default. Infima is a CSS framework designed to
4
+ * work well for content-centric websites.
5
+ */
6
+
7
+ /* You can override the default Infima variables here. */
8
+ :root {
9
+ --ifm-color-primary: #2e8555;
10
+ --ifm-color-primary-dark: #29784c;
11
+ --ifm-color-primary-darker: #277148;
12
+ --ifm-color-primary-darkest: #205d3b;
13
+ --ifm-color-primary-light: #33925d;
14
+ --ifm-color-primary-lighter: #359962;
15
+ --ifm-color-primary-lightest: #3cad6e;
16
+ --ifm-code-font-size: 95%;
17
+ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
18
+ }
19
+
20
+ /* For readability concerns, you should choose a lighter palette in dark mode. */
21
+ [data-theme='dark'] {
22
+ --ifm-color-primary: #25c2a0;
23
+ --ifm-color-primary-dark: #21af90;
24
+ --ifm-color-primary-darker: #1fa588;
25
+ --ifm-color-primary-darkest: #1a8870;
26
+ --ifm-color-primary-light: #29d5b0;
27
+ --ifm-color-primary-lighter: #32d8b4;
28
+ --ifm-color-primary-lightest: #4fddbf;
29
+ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
30
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * CSS files with the .module.css suffix will be treated as CSS modules
3
+ * and scoped locally.
4
+ */
5
+
6
+ .heroBanner {
7
+ padding: 4rem 0;
8
+ text-align: center;
9
+ position: relative;
10
+ overflow: hidden;
11
+ }
12
+
13
+ @media screen and (max-width: 996px) {
14
+ .heroBanner {
15
+ padding: 2rem;
16
+ }
17
+ }
18
+
19
+ .buttons {
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ }
@@ -0,0 +1,137 @@
1
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
2
+ import Layout from "@theme/Layout";
3
+
4
+ export default function Home(): JSX.Element {
5
+ const { siteConfig } = useDocusaurusContext();
6
+ return (
7
+ <Layout
8
+ title={`Hello from ${siteConfig.title}`}
9
+ description="Description will go into a meta tag in <head />"
10
+ >
11
+ <main
12
+ style={{
13
+ display: "flex",
14
+ flexDirection: "column",
15
+ alignSelf: "center",
16
+ width: "100vw",
17
+ background: "#111",
18
+ }}
19
+ >
20
+ <div
21
+ style={{
22
+ alignSelf: "center",
23
+ textAlign: "center",
24
+
25
+ color: "#fefefe",
26
+ padding: 20,
27
+ maxWidth: 800,
28
+ }}
29
+ >
30
+ <h1 style={{ fontSize: "4rem" }}>Electrobun</h1>
31
+ <div style={{}}>
32
+ <p>
33
+ Electrobun aims to be a complete solution-in-a-box for building,
34
+ updating, and shipping ultra fast, tiny, and cross-platform
35
+ desktop applications written in Typescript.
36
+ </p>
37
+ <img src="/img/electrobun-logo-256.png"></img>
38
+ <p>
39
+ Under the hood it uses bun to execute the main process and to
40
+ bundle webview typescript, and has native bindings written in zig.
41
+ </p>
42
+ </div>
43
+ <hr style={{ margin: "35px 0" }} />
44
+ <h2>Install Electrobun v0.1.0</h2>
45
+ <div
46
+ style={{
47
+ display: "flex",
48
+ border: "4px solid #e263a9",
49
+ borderRadius: 8,
50
+ padding: 8,
51
+ background: "#000",
52
+ fontSize: 20,
53
+ fontWeight: "bold",
54
+ width: 300,
55
+ alignSelf: "center",
56
+ margin: "auto",
57
+ }}
58
+ >
59
+ <span style={{ color: "#777", padding: "0 8px" }}>$</span>
60
+ <span style={{ color: "#aaa" }}>bun install electrobun</span>
61
+ </div>
62
+ <hr style={{ margin: "35px 0" }} />
63
+ <div
64
+ style={{
65
+ display: "flex",
66
+ margin: "auto",
67
+ textAlign: "left",
68
+ flexWrap: "wrap",
69
+ justifyContent: "space-evenly",
70
+ }}
71
+ >
72
+ <div
73
+ style={{
74
+ minWidth: 100,
75
+ maxWidth: 350,
76
+ padding: 20,
77
+ border: "2px solid black",
78
+ }}
79
+ >
80
+ <h3>Typescript</h3>
81
+ <p>
82
+ Write typescript for the main process and webviews without
83
+ having to think about it. One language, no hassle.
84
+ </p>
85
+ </div>
86
+
87
+ <div
88
+ style={{
89
+ minWidth: 100,
90
+ maxWidth: 350,
91
+ padding: 20,
92
+ border: "2px solid black",
93
+ }}
94
+ >
95
+ <h3>Fast</h3>
96
+ <p>
97
+ Security and Performance with isolation between the main and
98
+ webview processes and fast, typed, easy to implement RPC between
99
+ them.
100
+ </p>
101
+ </div>
102
+
103
+ <div
104
+ style={{
105
+ minWidth: 100,
106
+ maxWidth: 350,
107
+ padding: 20,
108
+ border: "2px solid black",
109
+ }}
110
+ >
111
+ <h3>Tiny</h3>
112
+ <p>
113
+ Small self-extracting app bundles ~12MB and tiny app updates as
114
+ small as 4KB. Ship often while saving bandwidth costs.
115
+ </p>
116
+ </div>
117
+
118
+ <div
119
+ style={{
120
+ minWidth: 100,
121
+ maxWidth: 350,
122
+ padding: 20,
123
+ border: "2px solid black",
124
+ }}
125
+ >
126
+ <h3>Batteries</h3>
127
+ <p>
128
+ Everything you need in one tightly integrated workflow to start
129
+ writing code in 5 minutes and distribute in 10.
130
+ </p>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </main>
135
+ </Layout>
136
+ );
137
+ }
File without changes
@@ -0,0 +1,7 @@
1
+ {
2
+ // This file is not used in compilation. It is here just for a nice editor experience.
3
+ "extends": "@docusaurus/tsconfig",
4
+ "compilerOptions": {
5
+ "baseUrl": "."
6
+ }
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrobun",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Build ultra fast, tiny, and cross-platform desktop apps with Typescript.",
5
5
  "license": "MIT",
6
6
  "author": "Blackboard Technologies Inc.",
@@ -11,7 +11,7 @@
11
11
  "./view": "./src/browser/index.ts"
12
12
  },
13
13
  "bin": {
14
- "electrobun": "src/cli/build/electrobun"
14
+ "electrobun": "src/cli/build/electrobun"
15
15
  },
16
16
  "homepage": "https://electrobun.dev",
17
17
  "repository": {
@@ -19,7 +19,7 @@
19
19
  "url": "https://github.com/blackboardsh/electrobun.git"
20
20
  },
21
21
  "scripts": {
22
- "start": "bun src/bun/index.ts",
22
+ "start": "bun src/bun/index.ts",
23
23
  "check-zig-version": "vendors/zig/zig version",
24
24
  "install-zig": "mkdir -p vendors/zig && curl -L https://ziglang.org/download/0.11.0/zig-macos-aarch64-0.11.0.tar.xz | tar -xJ --strip-components=1 -C vendors/zig zig-macos-aarch64-0.11.0/zig zig-macos-aarch64-0.11.0/lib",
25
25
  "build:objc:object": "mkdir -p src/objc/build && clang -c src/objc/objcWrapper.m -o src/objc/build/objcWrapper.o -fobjc-arc -fno-objc-msgsend-selector-stubs",
@@ -34,20 +34,25 @@
34
34
  "build:launcher:release": "cd src/launcher && ../../vendors/zig/zig build -Doptimize=ReleaseSmall",
35
35
  "build:extractor:release": "cd src/extractor && ../../vendors/zig/zig build -Doptimize=ReleaseSmall",
36
36
  "build:browser": "bun build src/browser/index.ts --outdir src/zig/build/",
37
- "build:cli": "bun build src/cli/index.ts --compile --outfile src/cli/build/electrobun",
37
+ "build:cli": "bun build src/cli/index.ts --compile --outfile src/cli/build/electrobun",
38
38
  "build:dev": "bun install && bun build:zig:trdiff && bun build:objc && bun build:browser && bun build:zig && bun build:launcher && bun build:extractor && bun build:cli",
39
39
  "build:release": "bun build:objc && bun build:zig:trdiff:release && bun build:browser && bun build:zig:release && bun build:launcher:release && bun build:extractor:release && bun build:cli",
40
40
  "release:dist": "bun build:release && cp src/launcher/zig-out/bin/launcher dist/launcher && cp src/extractor/zig-out/bin/extractor dist/extractor && cp src/bsdiff/zig-out/bin/bsdiff dist/bsdiff && cp src/bsdiff/zig-out/bin/bspatch dist/bspatch && cp src/zig/zig-out/bin/webview dist/webview && cp node_modules/.bin/bun dist/bun",
41
41
  "build:electrobun": "bun build:objc && bun build:browser && bun build:zig && bun build:bun",
42
42
  "dev:example": "bun build:dev && cd example && npm install && bun build:dev && bun start",
43
43
  "dev:example:rerun": "cd example && bun start",
44
- "dev:example:canary": "bun build:release && cd example && npm install && bun build:canary"
44
+ "dev:example:canary": "bun build:release && cd example && npm install && bun build:canary",
45
+ "dev:docs": "cd documentation && bun start",
46
+ "build:docs:release": "cd documentation && bun run build"
45
47
  },
46
48
  "devDependencies": {
47
49
  "@types/bun": "^1.0.8",
48
50
  "bun": "1.0.26"
49
51
  },
50
52
  "dependencies": {
51
- "rpc-anywhere": "1.5.0", "tar": "^6.2.1", "@oneidentity/zstd-js": "^1.0.3"
53
+ "@oneidentity/zstd-js": "^1.0.3",
54
+ "electrobun": "^0.0.2",
55
+ "rpc-anywhere": "1.5.0",
56
+ "tar": "^6.2.1"
52
57
  }
53
58
  }
@@ -384,8 +384,8 @@ class Electroview<T> {
384
384
 
385
385
  export { type RPCSchema, createRPC, Electroview };
386
386
 
387
- const ElectrobunView = {
387
+ const Electrobun = {
388
388
  Electroview,
389
389
  };
390
390
 
391
- export default ElectrobunView;
391
+ export default Electrobun;
@@ -16,6 +16,8 @@ import type { BuiltinBunToWebviewSchema } from "../../browser/builtinrpcSchema";
16
16
  const BrowserViewMap = {};
17
17
  let nextWebviewId = 1;
18
18
 
19
+ const CHUNK_SIZE = 4096; // 4KB
20
+
19
21
  type BrowserViewOptions<T = undefined> = {
20
22
  url: string | null;
21
23
  html: string | null;
@@ -213,8 +215,19 @@ export class BrowserView<T> {
213
215
  this.executeJavascript(wrappedMessage);
214
216
  }
215
217
 
218
+ // Note: the OS has a buffer limit on named pipes. If we overflow it
219
+ // it won't trigger the kevent for zig to read the pipe and we'll be stuck.
220
+ // so we have to chunk it
216
221
  executeJavascript(js: string) {
217
- this.inStream.write(js + "\n");
222
+ let offset = 0;
223
+ while (offset < js.length) {
224
+ const chunk = js.slice(offset, offset + CHUNK_SIZE);
225
+ this.inStream.write(chunk);
226
+ offset += CHUNK_SIZE;
227
+ }
228
+
229
+ // Ensure the newline is written after all chunks
230
+ this.inStream.write("\n");
218
231
  }
219
232
 
220
233
  loadURL(url: string) {
Binary file
package/src/cli/index.ts CHANGED
@@ -716,7 +716,9 @@ if (commandArg === "init") {
716
716
  const cacheBuster = Math.random().toString(36).substring(7);
717
717
  const updateJsonResponse = await fetch(
718
718
  urlToPrevUpdateJson + `?${cacheBuster}`
719
- );
719
+ ).catch((err) => {
720
+ console.log("bucketURL not found: ", err);
721
+ });
720
722
 
721
723
  const urlToLatestTarball = join(
722
724
  config.release.bucketUrl,
@@ -1,84 +0,0 @@
1
- ## Project Structure
2
-
3
- <pre>
4
- /src - electrobun's src code
5
- /src/browser - typescript compiles to the in-webview electrobun javascript api
6
- /src/bun - typescript compiles to the main process javascript api
7
- /src/objc - c-abi wrapped objective c, compiled to a static lib
8
- /src/zig - zig native bindings, compiles to the native renderer process.
9
- /src/zig/build - where the compiled src/objc ends up so zig can see it and embed it
10
- /src/cli - a cli for building and running developer apps, it reads electrobun.config files
11
- /example - Interactive example using the library.
12
- </pre>
13
-
14
- ## Building
15
-
16
- Tldr;
17
-
18
- - clang to compile objective c wrappers for macos in src/objc (.m files) into a static library, since objc is a superset of c the wrappers have intentionally been designed with c-compatible wrappers/apis
19
- - zig is built with zig's build system. must specify zig equivalent types for objc wrappers to map memory
20
- - electrobun in-webview-api that runs in all frames of the webviews is built using bun with a browser target
21
- - the in-webview-api and objc are built into src/zig/build/ so zig can see it
22
-
23
- ## IPC
24
-
25
- Bun spawns the zig bindings as a separate process. GUI applications require the main thread of a process to run a blocking event loop, so this is separate to the bun process.
26
-
27
- There are two categories of named pipes for IPC.
28
-
29
- 1. bun <-> zig. This is used for communicating with zig. ie: creating windows and webviews, and binding native handlers that need a response from bun like will-navigate.
30
- 2. bun <-> webview. Each webview gets its own pair of named pipes for communicating with bun.
31
-
32
- ### bun <-> zig
33
-
34
- There is a primary named pipe used to send rpc-anywhere encoded json messages between bun and zig on this pipe. There is a minimal zig implementation of rpc-anywhere that also implements a promise-like api in zig (freezes the main thread while waiting and unfreezes it returning a value).
35
-
36
- In order to simulate something promise-like in zig we send the request to bun and pause the main zig thread. We have a pipe listener on another thread waiting for a reply, when it gets a response it unfreezes the main thread and returns the value back to the function that was waiting.
37
-
38
- In general (whether receiving rpc requests, responses, and messages from bun) there is a performant loop in zig listening on another thread. We use native functions to group named pipe into a kqueue and let the process subscribe to events that continue the loop so it isn't busy waiting. For any gui-related rpc whe have to pass messages to the main thread to be executed.
39
-
40
- ### bun <-> webview
41
-
42
- When creating a webview a new named pipe pair is created. zig creates a bridge between the named pipe and the webview that passes anything between the named pipe and the webview so it's never deserialized in zig. We also have code in the webview for handling the other end of the RPC anywhere bun<->webview communication. By using a named pipe for each webview we eliminate the need for the zig bridge having to double wrap or partially de/serialize json messages to route them to the right webview which makes bun <-> webview communciation significantly faster.
43
-
44
- ## Events
45
-
46
- Electrobun.events is a custom event emitter. If we look at how the 'will-navigate' event works.
47
-
48
- 1. zig sends json rpc request to decide navigation over the main bun named pipe with a url and a webviewid
49
- 2. zig pauses the main thread simulating a promise-ish while listening on a separate named pipe listener thread
50
- 3. bun parses the json rpc and sees it's a 'will navigate' request
51
- 4. bun creates a new Electrobun.events.webview.willNavigate event with the data (url and webviewid).
52
- 5. bun then emits the event globally ('will-navigate') that could be listened to with Electrobun.events.on('will-navigate')
53
- 6. bun the passes the same event to a specific event ('will-navigate-<webviewId>' ie: will-navigate-1 for the webivew with id 1)
54
- 7. you could listen to this globally via Electrobun.events.on('will-navigate-1') if you wanted to. Since ids are incremented deterministically this allows for some interesting patterns like handling navigation for the first window created
55
- 8. you can also listen on the webview with myWebview.on('will-navigate'). Webview extends a "event emitter class' that essentially provides on, off, appendEventListener, etc. but instead of being an event listener it modifies the event name to include its id, and subscribes the handler to the main event emitter. So it basically does Electrobun.events.on('will-navigate-1') for you without you having to think about the webview's id and providing other lifecycle handling for you.
56
- 9. the event object has a response getter/setter and a clearResponse method that allows any handler to respond with a value as well as a 'responseWasSet' flag. so in any handler you can both check if another handler set a response, and if you want override or modify the response.
57
- 10. the response is then sent serialized as an rpc response and sent back to zig which is listening on another thread and unfreezes the main thread returning the value
58
-
59
- Global events are always called before specific events.
60
-
61
- ## Working on Electrobun
62
-
63
- There are some npm scripts to facilitate building everything from the objc, zig, bundling webview api, transpiling the bun api and so an, as well as building the example app and executing it.
64
-
65
- The example app is meant to be an interactive example of Electrobun's functionality, it's useful when implementing new functionality in any part of Electrobun to have everything rebuilt so you can interact with it in the example app which then doubles as a demo app for developers wanting to explore what Electrobun can do.
66
-
67
- You currently need zig installed globally, and to be on an ARM mac. I dunno if you have to install xcode or xcode tools to get clang on your system. Will iron out a better dev flow in the future.
68
-
69
- For now you can simply
70
-
71
- 1. clone the repo
72
- 2. in the repo root run `bun run dev:example`
73
-
74
- If you take a look at the repo's package.json as well as example app's package.json and electrobun.config you'll get a better sense of what's happening for each step.
75
-
76
- ## How Developer apps are built
77
-
78
- > Note: in order for an application to get keyboard focus on macos you can't run it as a subprocess of the terminal which greedily steals keyboard input, so it needs to be built into an app bundle.
79
-
80
- This part is wip, but currently we create a minimal macos app bundle and execute it. There is a launcher shell script which calls bun with your typescript. It configures stdout/err to write to a named pipe log file and starts listening to it so you get the output in the terminal.
81
-
82
- You can cmd+c to stop that, but for now to quit your running app you have to close the window.
83
-
84
- A better dev flow, as well as installing bun to a global location outside the app bundle is being actively developed.
File without changes
File without changes
File without changes
File without changes