electrobun 1.18.1 → 1.18.4-beta.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.
- package/README.md +1 -0
- package/dist/api/bun/ElectrobunConfig.ts +20 -0
- package/dist/api/bun/core/BrowserView.ts +29 -47
- package/dist/api/bun/core/BrowserWindow.ts +14 -7
- package/dist/api/bun/core/BuildConfig.ts +31 -4
- package/dist/api/bun/core/GpuWindow.ts +13 -6
- package/dist/api/bun/core/Tray.ts +33 -32
- package/dist/api/bun/proc/native.ts +682 -655
- package/dist/main.js +26 -22
- package/dist/preload-full.js +885 -0
- package/dist/preload-sandboxed.js +111 -0
- package/dist/zig-sdk/electrobun.zig +1979 -0
- package/package.json +2 -3
- package/src/cli/index.ts +313 -135
- package/dist/api/bun/core/windowIds.ts +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electrobun",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.4-beta.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.",
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
"exports": {
|
|
15
15
|
".": "./dist/api/bun/index.ts",
|
|
16
16
|
"./bun": "./dist/api/bun/index.ts",
|
|
17
|
-
"./view": "./dist/api/browser/index.ts"
|
|
18
|
-
"./carrot": "./dist/api/carrot/bun.ts"
|
|
17
|
+
"./view": "./dist/api/browser/index.ts"
|
|
19
18
|
},
|
|
20
19
|
"type": "module",
|
|
21
20
|
"bin": {
|
package/src/cli/index.ts
CHANGED
|
@@ -111,6 +111,9 @@ function getPlatformPaths(
|
|
|
111
111
|
BUN_BINARY: join(platformDistDir, "bun") + binExt,
|
|
112
112
|
LAUNCHER_DEV: join(platformDistDir, "electrobun") + binExt,
|
|
113
113
|
LAUNCHER_RELEASE: join(platformDistDir, "launcher") + binExt,
|
|
114
|
+
CORE_MACOS: join(platformDistDir, "libElectrobunCore.dylib"),
|
|
115
|
+
CORE_WIN: join(platformDistDir, "ElectrobunCore.dll"),
|
|
116
|
+
CORE_LINUX: join(platformDistDir, "libElectrobunCore.so"),
|
|
114
117
|
NATIVE_WRAPPER_MACOS: join(platformDistDir, "libNativeWrapper.dylib"),
|
|
115
118
|
NATIVE_WRAPPER_WIN: join(platformDistDir, "libNativeWrapper.dll"),
|
|
116
119
|
NATIVE_WRAPPER_LINUX: join(platformDistDir, "libNativeWrapper.so"),
|
|
@@ -134,6 +137,8 @@ function getPlatformPaths(
|
|
|
134
137
|
// These work with existing package.json and development workflow
|
|
135
138
|
MAIN_JS: join(sharedDistDir, "main.js"),
|
|
136
139
|
API_DIR: join(sharedDistDir, "api"),
|
|
140
|
+
PRELOAD_FULL_JS: join(sharedDistDir, "preload-full.js"),
|
|
141
|
+
PRELOAD_SANDBOXED_JS: join(sharedDistDir, "preload-sandboxed.js"),
|
|
137
142
|
};
|
|
138
143
|
}
|
|
139
144
|
|
|
@@ -141,6 +146,135 @@ function getPlatformPaths(
|
|
|
141
146
|
// @ts-expect-error - reserved for future use
|
|
142
147
|
const _PATHS = getPlatformPaths(OS, ARCH);
|
|
143
148
|
|
|
149
|
+
function getVendoredZigBinaryPath(): string {
|
|
150
|
+
return join(
|
|
151
|
+
ELECTROBUN_DEP_PATH,
|
|
152
|
+
"vendors",
|
|
153
|
+
"zig",
|
|
154
|
+
OS === "win" ? "zig.exe" : "zig",
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function getZigTarget(
|
|
159
|
+
targetOS: "macos" | "win" | "linux",
|
|
160
|
+
targetArch: "arm64" | "x64",
|
|
161
|
+
): string {
|
|
162
|
+
if (targetOS === "win") {
|
|
163
|
+
return "x86_64-windows";
|
|
164
|
+
}
|
|
165
|
+
if (targetOS === "linux") {
|
|
166
|
+
return targetArch === "arm64" ? "aarch64-linux" : "x86_64-linux";
|
|
167
|
+
}
|
|
168
|
+
return targetArch === "arm64" ? "aarch64-macos" : "x86_64-macos";
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getCEFHelperBaseName(mainProcess: "bun" | "zig"): string {
|
|
172
|
+
return mainProcess === "zig" ? "main" : "bun";
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function getCEFHelperNames(mainProcess: "bun" | "zig"): string[] {
|
|
176
|
+
const baseName = getCEFHelperBaseName(mainProcess);
|
|
177
|
+
return [
|
|
178
|
+
`${baseName} Helper`,
|
|
179
|
+
`${baseName} Helper (Alerts)`,
|
|
180
|
+
`${baseName} Helper (GPU)`,
|
|
181
|
+
`${baseName} Helper (Plugin)`,
|
|
182
|
+
`${baseName} Helper (Renderer)`,
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function buildZigMainExecutable(options: {
|
|
187
|
+
entrypoint: string;
|
|
188
|
+
buildFolder: string;
|
|
189
|
+
targetOS: "macos" | "win" | "linux";
|
|
190
|
+
targetArch: "arm64" | "x64";
|
|
191
|
+
buildEnvironment: "dev" | "canary" | "stable";
|
|
192
|
+
}) {
|
|
193
|
+
const zigBinary = getVendoredZigBinaryPath();
|
|
194
|
+
if (!existsSync(zigBinary)) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
`Vendored Zig compiler not found at ${zigBinary}. Rebuild electrobun/package so vendors/zig is available.`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const zigSdkPath = join(ELECTROBUN_DEP_PATH, "dist", "zig-sdk", "electrobun.zig");
|
|
201
|
+
if (!existsSync(zigSdkPath)) {
|
|
202
|
+
throw new Error(`Electrobun Zig SDK not found at ${zigSdkPath}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const binExt = options.targetOS === "win" ? ".exe" : "";
|
|
206
|
+
const tempBuildDir = join(
|
|
207
|
+
options.buildFolder,
|
|
208
|
+
".electrobun-zig-main",
|
|
209
|
+
`${options.targetOS}-${options.targetArch}`,
|
|
210
|
+
);
|
|
211
|
+
const relativeZigSdkPath = path.relative(tempBuildDir, zigSdkPath) || ".";
|
|
212
|
+
const relativeEntrypointPath = path.relative(tempBuildDir, options.entrypoint) || ".";
|
|
213
|
+
const zigOutBin = join(tempBuildDir, "zig-out", "bin", "main" + binExt);
|
|
214
|
+
const buildScriptPath = join(tempBuildDir, "build.zig");
|
|
215
|
+
mkdirSync(tempBuildDir, { recursive: true });
|
|
216
|
+
|
|
217
|
+
const buildScript = `const std = @import("std");
|
|
218
|
+
|
|
219
|
+
pub fn build(b: *std.Build) void {
|
|
220
|
+
const target = b.standardTargetOptions(.{});
|
|
221
|
+
const optimize = b.standardOptimizeOption(.{});
|
|
222
|
+
|
|
223
|
+
const electrobun = b.createModule(.{
|
|
224
|
+
.root_source_file = b.path(${JSON.stringify(relativeZigSdkPath)}),
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const exe = b.addExecutable(.{
|
|
228
|
+
.name = "main",
|
|
229
|
+
.root_source_file = b.path(${JSON.stringify(relativeEntrypointPath)}),
|
|
230
|
+
.target = target,
|
|
231
|
+
.optimize = optimize,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
exe.root_module.addImport("electrobun", electrobun);
|
|
235
|
+
exe.linkLibC();
|
|
236
|
+
b.installArtifact(exe);
|
|
237
|
+
}
|
|
238
|
+
`;
|
|
239
|
+
writeFileSync(buildScriptPath, buildScript, "utf8");
|
|
240
|
+
|
|
241
|
+
const zigArgs = [
|
|
242
|
+
"build",
|
|
243
|
+
`-Dtarget=${getZigTarget(options.targetOS, options.targetArch)}`,
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
if (options.targetOS === "win") {
|
|
247
|
+
zigArgs.push("-Dcpu=baseline");
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (options.buildEnvironment !== "dev") {
|
|
251
|
+
zigArgs.push("-Doptimize=ReleaseSmall");
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const result = Bun.spawnSync([zigBinary, ...zigArgs], {
|
|
255
|
+
cwd: tempBuildDir,
|
|
256
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
if (result.exitCode !== 0) {
|
|
260
|
+
const stdout = result.stdout ? new TextDecoder().decode(result.stdout) : "";
|
|
261
|
+
const stderr = result.stderr ? new TextDecoder().decode(result.stderr) : "";
|
|
262
|
+
if (stdout.trim()) {
|
|
263
|
+
console.error(stdout);
|
|
264
|
+
}
|
|
265
|
+
if (stderr.trim()) {
|
|
266
|
+
console.error(stderr);
|
|
267
|
+
}
|
|
268
|
+
throw new Error("Build failed: zig main process compilation failed");
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (!existsSync(zigOutBin)) {
|
|
272
|
+
throw new Error(`Zig main process binary was not produced at ${zigOutBin}`);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return zigOutBin;
|
|
276
|
+
}
|
|
277
|
+
|
|
144
278
|
async function ensureCoreDependencies(
|
|
145
279
|
targetOS?: "macos" | "win" | "linux",
|
|
146
280
|
targetArch?: "arm64" | "x64",
|
|
@@ -1483,6 +1617,7 @@ const defaultConfig = {
|
|
|
1483
1617
|
build: {
|
|
1484
1618
|
buildFolder: "build",
|
|
1485
1619
|
artifactFolder: "artifacts",
|
|
1620
|
+
mainProcess: "bun" as "bun" | "zig",
|
|
1486
1621
|
useAsar: false,
|
|
1487
1622
|
asarUnpack: undefined as string[] | undefined, // Glob patterns for files to exclude from ASAR (e.g., ["*.node", "*.dll"])
|
|
1488
1623
|
cefVersion: undefined as string | undefined, // Override CEF version: "CEF_VERSION+chromium-CHROMIUM_VERSION"
|
|
@@ -1524,6 +1659,9 @@ const defaultConfig = {
|
|
|
1524
1659
|
bun: {
|
|
1525
1660
|
entrypoint: "src/bun/index.ts",
|
|
1526
1661
|
},
|
|
1662
|
+
zig: {
|
|
1663
|
+
entrypoint: "src/zig/main.zig",
|
|
1664
|
+
},
|
|
1527
1665
|
views: undefined as
|
|
1528
1666
|
| Record<string, { entrypoint: string; [key: string]: unknown }>
|
|
1529
1667
|
| undefined,
|
|
@@ -2078,8 +2216,10 @@ ${utiDecls}
|
|
|
2078
2216
|
// Get environment
|
|
2079
2217
|
const envArg =
|
|
2080
2218
|
process.argv.find((arg) => arg.startsWith("--env="))?.split("=")[1] || "";
|
|
2081
|
-
const buildEnvironment = ["dev", "canary", "stable"].includes(
|
|
2082
|
-
|
|
2219
|
+
const buildEnvironment: "dev" | "canary" | "stable" = ["dev", "canary", "stable"].includes(
|
|
2220
|
+
envArg,
|
|
2221
|
+
)
|
|
2222
|
+
? (envArg as "dev" | "canary" | "stable")
|
|
2083
2223
|
: "dev";
|
|
2084
2224
|
|
|
2085
2225
|
try {
|
|
@@ -2110,7 +2250,7 @@ ${utiDecls}
|
|
|
2110
2250
|
|
|
2111
2251
|
async function runBuild(
|
|
2112
2252
|
config: Awaited<ReturnType<typeof getConfig>>,
|
|
2113
|
-
buildEnvironment:
|
|
2253
|
+
buildEnvironment: "dev" | "canary" | "stable",
|
|
2114
2254
|
) {
|
|
2115
2255
|
// Determine current platform as default target
|
|
2116
2256
|
const currentTarget = { os: OS, arch: ARCH };
|
|
@@ -2395,17 +2535,31 @@ Categories=Utility;Application;
|
|
|
2395
2535
|
rmSync(buildFolder, { recursive: true });
|
|
2396
2536
|
}
|
|
2397
2537
|
mkdirSync(buildFolder, { recursive: true });
|
|
2398
|
-
|
|
2538
|
+
|
|
2539
|
+
const mainProcess = config.build.mainProcess ?? "bun";
|
|
2399
2540
|
const bunConfig = config.build.bun;
|
|
2400
2541
|
const bunSource = join(projectRoot, bunConfig.entrypoint);
|
|
2542
|
+
const zigConfig = config.build.zig;
|
|
2543
|
+
const zigSource = join(projectRoot, zigConfig.entrypoint);
|
|
2401
2544
|
|
|
2402
|
-
if (
|
|
2545
|
+
if (mainProcess === "bun") {
|
|
2546
|
+
if (!existsSync(bunSource)) {
|
|
2547
|
+
throw new Error(
|
|
2548
|
+
`failed to bundle ${bunSource} because it doesn't exist.\n You need a config.build.bun.entrypoint source file to build.`,
|
|
2549
|
+
);
|
|
2550
|
+
}
|
|
2551
|
+
} else if (!existsSync(zigSource)) {
|
|
2403
2552
|
throw new Error(
|
|
2404
|
-
`failed to
|
|
2553
|
+
`failed to compile ${zigSource} because it doesn't exist.\n You need a config.build.zig.entrypoint source file to build.`,
|
|
2405
2554
|
);
|
|
2406
2555
|
}
|
|
2407
2556
|
|
|
2408
2557
|
const isCarrotOnly = config.build.carrot?.carrotOnly === true;
|
|
2558
|
+
if (config.build.carrot && mainProcess === "zig") {
|
|
2559
|
+
throw new Error(
|
|
2560
|
+
`build.carrot is not supported with build.mainProcess = "zig" yet.`,
|
|
2561
|
+
);
|
|
2562
|
+
}
|
|
2409
2563
|
|
|
2410
2564
|
// build macos bundle
|
|
2411
2565
|
// Use display name (with spaces) for macOS bundle folders, sanitized name for other platforms
|
|
@@ -2438,6 +2592,17 @@ Categories=Utility;Application;
|
|
|
2438
2592
|
mkdirSync(appBundleAppCodePath, { recursive: true });
|
|
2439
2593
|
}
|
|
2440
2594
|
|
|
2595
|
+
let zigMainBinarySourcePath: string | null = null;
|
|
2596
|
+
if (mainProcess === "zig") {
|
|
2597
|
+
zigMainBinarySourcePath = await buildZigMainExecutable({
|
|
2598
|
+
entrypoint: zigSource,
|
|
2599
|
+
buildFolder,
|
|
2600
|
+
targetOS,
|
|
2601
|
+
targetArch: targetARCH,
|
|
2602
|
+
buildEnvironment,
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2441
2606
|
// const bundledBunPath = join(appBundleMacOSPath, 'bun');
|
|
2442
2607
|
// cpSync(bunPath, bundledBunPath);
|
|
2443
2608
|
|
|
@@ -2610,105 +2775,121 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
2610
2775
|
}
|
|
2611
2776
|
}
|
|
2612
2777
|
|
|
2613
|
-
cpSync(targetPaths.
|
|
2778
|
+
cpSync(targetPaths.PRELOAD_FULL_JS, join(appBundleFolderResourcesPath, "preload-full.js"), {
|
|
2614
2779
|
dereference: true,
|
|
2615
2780
|
});
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
config.build.bunVersion,
|
|
2623
|
-
config.build.bunnyBun,
|
|
2781
|
+
cpSync(
|
|
2782
|
+
targetPaths.PRELOAD_SANDBOXED_JS,
|
|
2783
|
+
join(appBundleFolderResourcesPath, "preload-sandboxed.js"),
|
|
2784
|
+
{
|
|
2785
|
+
dereference: true,
|
|
2786
|
+
},
|
|
2624
2787
|
);
|
|
2625
|
-
// Note: .bin/bun binary in node_modules is a symlink to the versioned one in another place
|
|
2626
|
-
// in node_modules, so we have to dereference here to get the actual binary in the bundle.
|
|
2627
|
-
const bunBinaryDestInBundlePath =
|
|
2628
|
-
join(appBundleMacOSPath, "bun") + targetBinExt;
|
|
2629
|
-
const destFolder2 = dirname(bunBinaryDestInBundlePath);
|
|
2630
|
-
if (!existsSync(destFolder2)) {
|
|
2631
|
-
// console.info('creating folder: ', destFolder);
|
|
2632
|
-
mkdirSync(destFolder2, { recursive: true });
|
|
2633
|
-
}
|
|
2634
|
-
cpSync(bunBinarySourcePath, bunBinaryDestInBundlePath, {
|
|
2635
|
-
dereference: true,
|
|
2636
|
-
});
|
|
2637
2788
|
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
const icuDataSource = icuDataFileName ? join(bunDir, icuDataFileName) : "";
|
|
2643
|
-
if (icuDataFileName && existsSync(icuDataSource) && targetOS !== "macos") {
|
|
2644
|
-
const icuDataDest = join(appBundleMacOSPath, icuDataFileName);
|
|
2645
|
-
|
|
2646
|
-
const locales = config.build?.locales;
|
|
2647
|
-
if (locales && locales !== "*" && Array.isArray(locales) && locales.length > 0) {
|
|
2648
|
-
// Trim ICU data to specified locales using icupkg
|
|
2649
|
-
try {
|
|
2650
|
-
await trimICUData(icuDataSource, icuDataDest, locales);
|
|
2651
|
-
const originalSize = statSync(icuDataSource).size;
|
|
2652
|
-
const trimmedSize = statSync(icuDataDest).size;
|
|
2653
|
-
console.log(
|
|
2654
|
-
`Trimmed ICU data: ${(originalSize / 1024 / 1024).toFixed(1)}MB → ${(trimmedSize / 1024 / 1024).toFixed(1)}MB (locales: ${locales.join(", ")})`,
|
|
2655
|
-
);
|
|
2656
|
-
} catch (error) {
|
|
2657
|
-
console.warn(`Warning: Failed to trim ICU data, copying full file: ${error}`);
|
|
2658
|
-
cpSync(icuDataSource, icuDataDest);
|
|
2659
|
-
}
|
|
2660
|
-
} else {
|
|
2661
|
-
cpSync(icuDataSource, icuDataDest);
|
|
2662
|
-
console.log(`Copied ICU data file: ${icuDataFileName}`);
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2789
|
+
if (mainProcess === "bun") {
|
|
2790
|
+
cpSync(targetPaths.MAIN_JS, join(appBundleFolderResourcesPath, "main.js"), {
|
|
2791
|
+
dereference: true,
|
|
2792
|
+
});
|
|
2665
2793
|
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
const
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2794
|
+
// Bun runtime binary
|
|
2795
|
+
// todo (yoav): this only works for the current architecture
|
|
2796
|
+
const bunBinarySourcePath = await ensureBunBinary(
|
|
2797
|
+
currentTarget.os,
|
|
2798
|
+
currentTarget.arch,
|
|
2799
|
+
config.build.bunVersion,
|
|
2800
|
+
config.build.bunnyBun,
|
|
2801
|
+
);
|
|
2802
|
+
// Note: .bin/bun binary in node_modules is a symlink to the versioned one in another place
|
|
2803
|
+
// in node_modules, so we have to dereference here to get the actual binary in the bundle.
|
|
2804
|
+
const bunBinaryDestInBundlePath =
|
|
2805
|
+
join(appBundleMacOSPath, "bun") + targetBinExt;
|
|
2806
|
+
const destFolder2 = dirname(bunBinaryDestInBundlePath);
|
|
2807
|
+
if (!existsSync(destFolder2)) {
|
|
2808
|
+
mkdirSync(destFolder2, { recursive: true });
|
|
2809
|
+
}
|
|
2810
|
+
cpSync(bunBinarySourcePath, bunBinaryDestInBundlePath, {
|
|
2811
|
+
dereference: true,
|
|
2812
|
+
});
|
|
2673
2813
|
|
|
2674
|
-
if (
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2814
|
+
// Copy ICU data file if it exists (Linux/Windows external ICU builds)
|
|
2815
|
+
// ICU version varies per platform WebKit build, so detect the filename dynamically
|
|
2816
|
+
const bunDir = dirname(bunBinarySourcePath);
|
|
2817
|
+
const icuDataFileName = readdirSync(bunDir).find((f) => /^icudt\d+l\.dat$/.test(f));
|
|
2818
|
+
const icuDataSource = icuDataFileName ? join(bunDir, icuDataFileName) : "";
|
|
2819
|
+
if (icuDataFileName && existsSync(icuDataSource) && targetOS !== "macos") {
|
|
2820
|
+
const icuDataDest = join(appBundleMacOSPath, icuDataFileName);
|
|
2678
2821
|
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
const
|
|
2684
|
-
|
|
2685
|
-
iconPath = tempIcoPath;
|
|
2822
|
+
const locales = config.build?.locales;
|
|
2823
|
+
if (locales && locales !== "*" && Array.isArray(locales) && locales.length > 0) {
|
|
2824
|
+
try {
|
|
2825
|
+
await trimICUData(icuDataSource, icuDataDest, locales);
|
|
2826
|
+
const originalSize = statSync(icuDataSource).size;
|
|
2827
|
+
const trimmedSize = statSync(icuDataDest).size;
|
|
2686
2828
|
console.log(
|
|
2687
|
-
`
|
|
2829
|
+
`Trimmed ICU data: ${(originalSize / 1024 / 1024).toFixed(1)}MB → ${(trimmedSize / 1024 / 1024).toFixed(1)}MB (locales: ${locales.join(", ")})`,
|
|
2688
2830
|
);
|
|
2831
|
+
} catch (error) {
|
|
2832
|
+
console.warn(`Warning: Failed to trim ICU data, copying full file: ${error}`);
|
|
2833
|
+
cpSync(icuDataSource, icuDataDest);
|
|
2689
2834
|
}
|
|
2835
|
+
} else {
|
|
2836
|
+
cpSync(icuDataSource, icuDataDest);
|
|
2837
|
+
console.log(`Copied ICU data file: ${icuDataFileName}`);
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2690
2840
|
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
console.log(`Successfully embedded icon into bun.exe`);
|
|
2841
|
+
// Embed icon into bun.exe on Windows
|
|
2842
|
+
if (targetOS === "win" && config.build.win?.icon) {
|
|
2843
|
+
const iconSourcePath =
|
|
2844
|
+
config.build.win.icon.startsWith("/") ||
|
|
2845
|
+
config.build.win.icon.match(/^[a-zA-Z]:/)
|
|
2846
|
+
? config.build.win.icon
|
|
2847
|
+
: join(projectRoot, config.build.win.icon);
|
|
2699
2848
|
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2849
|
+
if (existsSync(iconSourcePath)) {
|
|
2850
|
+
console.log(`Embedding icon into bun.exe: ${iconSourcePath}`);
|
|
2851
|
+
try {
|
|
2852
|
+
let iconPath = iconSourcePath;
|
|
2853
|
+
|
|
2854
|
+
if (iconSourcePath.toLowerCase().endsWith(".png")) {
|
|
2855
|
+
const pngToIco = (await import("png-to-ico")).default;
|
|
2856
|
+
const tempIcoPath = join(buildFolder, "temp-bun-icon.ico");
|
|
2857
|
+
const icoBuffer = await pngToIco(iconSourcePath);
|
|
2858
|
+
writeFileSync(tempIcoPath, new Uint8Array(icoBuffer));
|
|
2859
|
+
iconPath = tempIcoPath;
|
|
2860
|
+
console.log(
|
|
2861
|
+
`Converted PNG to ICO format for bun.exe: ${tempIcoPath}`,
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
const { execFileSync } = await import("child_process");
|
|
2866
|
+
const rceditPkgPath = require.resolve("rcedit/package.json");
|
|
2867
|
+
const rceditDir = dirname(rceditPkgPath);
|
|
2868
|
+
const rceditX64 = join(rceditDir, "bin", "rcedit-x64.exe");
|
|
2869
|
+
const rceditExe = existsSync(rceditX64) ? rceditX64 : join(rceditDir, "bin", "rcedit.exe");
|
|
2870
|
+
execFileSync(rceditExe, [bunBinaryDestInBundlePath, "--set-icon", iconPath]);
|
|
2871
|
+
console.log(`Successfully embedded icon into bun.exe`);
|
|
2872
|
+
|
|
2873
|
+
if (iconPath !== iconSourcePath && existsSync(iconPath)) {
|
|
2874
|
+
unlinkSync(iconPath);
|
|
2875
|
+
}
|
|
2876
|
+
} catch (error) {
|
|
2877
|
+
console.warn(`Warning: Failed to embed icon into bun.exe: ${error}`);
|
|
2703
2878
|
}
|
|
2704
|
-
} catch (error) {
|
|
2705
|
-
console.warn(`Warning: Failed to embed icon into bun.exe: ${error}`);
|
|
2706
2879
|
}
|
|
2707
2880
|
}
|
|
2881
|
+
} else if (zigMainBinarySourcePath) {
|
|
2882
|
+
cpSync(zigMainBinarySourcePath, join(appBundleMacOSPath, "main") + targetBinExt, {
|
|
2883
|
+
dereference: true,
|
|
2884
|
+
});
|
|
2708
2885
|
}
|
|
2709
2886
|
|
|
2710
2887
|
// copy native wrapper dynamic library
|
|
2711
2888
|
if (targetOS === "macos") {
|
|
2889
|
+
cpSync(targetPaths.CORE_MACOS, join(appBundleMacOSPath, "libElectrobunCore.dylib"), {
|
|
2890
|
+
dereference: true,
|
|
2891
|
+
});
|
|
2892
|
+
|
|
2712
2893
|
const nativeWrapperMacosSource = targetPaths.NATIVE_WRAPPER_MACOS;
|
|
2713
2894
|
const nativeWrapperMacosDestination = join(
|
|
2714
2895
|
appBundleMacOSPath,
|
|
@@ -2718,6 +2899,10 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
2718
2899
|
dereference: true,
|
|
2719
2900
|
});
|
|
2720
2901
|
} else if (targetOS === "win") {
|
|
2902
|
+
cpSync(targetPaths.CORE_WIN, join(appBundleMacOSPath, "ElectrobunCore.dll"), {
|
|
2903
|
+
dereference: true,
|
|
2904
|
+
});
|
|
2905
|
+
|
|
2721
2906
|
const nativeWrapperMacosSource = targetPaths.NATIVE_WRAPPER_WIN;
|
|
2722
2907
|
const nativeWrapperMacosDestination = join(
|
|
2723
2908
|
appBundleMacOSPath,
|
|
@@ -2737,6 +2922,9 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
2737
2922
|
} else if (targetOS === "linux") {
|
|
2738
2923
|
// Choose the appropriate native wrapper based on bundleCEF setting
|
|
2739
2924
|
const useCEF = config.build.linux?.bundleCEF;
|
|
2925
|
+
cpSync(targetPaths.CORE_LINUX, join(appBundleMacOSPath, "libElectrobunCore.so"), {
|
|
2926
|
+
dereference: true,
|
|
2927
|
+
});
|
|
2740
2928
|
const nativeWrapperLinuxSource = useCEF
|
|
2741
2929
|
? targetPaths.NATIVE_WRAPPER_LINUX_CEF
|
|
2742
2930
|
: targetPaths.NATIVE_WRAPPER_LINUX;
|
|
@@ -2822,13 +3010,7 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
2822
3010
|
});
|
|
2823
3011
|
|
|
2824
3012
|
// cef helpers
|
|
2825
|
-
const cefHelperNames =
|
|
2826
|
-
"bun Helper",
|
|
2827
|
-
"bun Helper (Alerts)",
|
|
2828
|
-
"bun Helper (GPU)",
|
|
2829
|
-
"bun Helper (Plugin)",
|
|
2830
|
-
"bun Helper (Renderer)",
|
|
2831
|
-
];
|
|
3013
|
+
const cefHelperNames = getCEFHelperNames(mainProcess);
|
|
2832
3014
|
|
|
2833
3015
|
const helperSourcePath = targetPaths.CEF_HELPER_MACOS;
|
|
2834
3016
|
cefHelperNames.forEach((helperName) => {
|
|
@@ -2909,13 +3091,7 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
2909
3091
|
}
|
|
2910
3092
|
|
|
2911
3093
|
// Copy CEF helper processes with different names
|
|
2912
|
-
const cefHelperNames =
|
|
2913
|
-
"bun Helper",
|
|
2914
|
-
"bun Helper (Alerts)",
|
|
2915
|
-
"bun Helper (GPU)",
|
|
2916
|
-
"bun Helper (Plugin)",
|
|
2917
|
-
"bun Helper (Renderer)",
|
|
2918
|
-
];
|
|
3094
|
+
const cefHelperNames = getCEFHelperNames(mainProcess);
|
|
2919
3095
|
|
|
2920
3096
|
const helperSourcePath = targetPaths.CEF_HELPER_WIN;
|
|
2921
3097
|
if (existsSync(helperSourcePath)) {
|
|
@@ -3047,13 +3223,7 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
3047
3223
|
});
|
|
3048
3224
|
|
|
3049
3225
|
// Copy CEF helper processes with different names
|
|
3050
|
-
const cefHelperNames =
|
|
3051
|
-
"bun Helper",
|
|
3052
|
-
"bun Helper (Alerts)",
|
|
3053
|
-
"bun Helper (GPU)",
|
|
3054
|
-
"bun Helper (Plugin)",
|
|
3055
|
-
"bun Helper (Renderer)",
|
|
3056
|
-
];
|
|
3226
|
+
const cefHelperNames = getCEFHelperNames(mainProcess);
|
|
3057
3227
|
|
|
3058
3228
|
const helperSourcePath = targetPaths.CEF_HELPER_LINUX;
|
|
3059
3229
|
if (existsSync(helperSourcePath)) {
|
|
@@ -3222,22 +3392,22 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
3222
3392
|
}
|
|
3223
3393
|
} // end if (!isCarrotOnly)
|
|
3224
3394
|
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
});
|
|
3395
|
+
if (mainProcess === "bun") {
|
|
3396
|
+
// transpile developer's bun code
|
|
3397
|
+
const bunDestFolder = join(appBundleAppCodePath, "bun");
|
|
3398
|
+
const { entrypoint: _bunEntrypoint, ...bunBuildOptions } = bunConfig;
|
|
3399
|
+
const buildResult = await Bun.build({
|
|
3400
|
+
...bunBuildOptions,
|
|
3401
|
+
entrypoints: [bunSource],
|
|
3402
|
+
outdir: bunDestFolder,
|
|
3403
|
+
target: "bun",
|
|
3404
|
+
});
|
|
3236
3405
|
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3406
|
+
if (!buildResult.success) {
|
|
3407
|
+
console.error("failed to build", bunSource);
|
|
3408
|
+
printBuildLogs(buildResult.logs);
|
|
3409
|
+
throw new Error("Build failed: bun build failed");
|
|
3410
|
+
}
|
|
3241
3411
|
}
|
|
3242
3412
|
|
|
3243
3413
|
// transpile developer's view code
|
|
@@ -3676,13 +3846,16 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
3676
3846
|
const bundlesCEF = platformConfig?.bundleCEF ?? false;
|
|
3677
3847
|
|
|
3678
3848
|
const buildJsonObj: Record<string, unknown> = {
|
|
3849
|
+
mainProcess,
|
|
3679
3850
|
defaultRenderer: platformConfig?.defaultRenderer ?? "native",
|
|
3680
3851
|
availableRenderers: bundlesCEF ? ["native", "cef"] : ["native"],
|
|
3681
3852
|
runtime: config.runtime ?? {},
|
|
3682
3853
|
...(bundlesCEF
|
|
3683
3854
|
? { cefVersion: config.build?.cefVersion ?? DEFAULT_CEF_VERSION_STRING }
|
|
3684
3855
|
: {}),
|
|
3685
|
-
|
|
3856
|
+
...(mainProcess === "bun"
|
|
3857
|
+
? { bunVersion: config.build?.bunVersion ?? BUN_VERSION }
|
|
3858
|
+
: {}),
|
|
3686
3859
|
...(config.build?.bunnyBun ? { bunnyBun: config.build.bunnyBun } : {}),
|
|
3687
3860
|
};
|
|
3688
3861
|
|
|
@@ -3760,10 +3933,9 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
3760
3933
|
// Tar the app bundle for all platforms
|
|
3761
3934
|
createTar(tarPath, buildFolder, [basename(appBundleFolderPath)]);
|
|
3762
3935
|
|
|
3763
|
-
//
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
}
|
|
3936
|
+
// This branch only runs for non-dev release packaging, so the temp app bundle
|
|
3937
|
+
// can always be removed after the tarball is produced.
|
|
3938
|
+
rmSync(appBundleFolderPath, { recursive: true });
|
|
3767
3939
|
|
|
3768
3940
|
// generate bsdiff
|
|
3769
3941
|
// https://storage.googleapis.com/eggbun-static/electrobun-playground/canary/ElectrobunPlayground-canary.app.tar.zst
|
|
@@ -4443,10 +4615,15 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
4443
4615
|
const watchDirs = new Set<string>();
|
|
4444
4616
|
|
|
4445
4617
|
// Bun entrypoint directory
|
|
4446
|
-
if (config.build.bun?.entrypoint) {
|
|
4618
|
+
if (config.build.mainProcess !== "zig" && config.build.bun?.entrypoint) {
|
|
4447
4619
|
watchDirs.add(join(projectRoot, dirname(config.build.bun.entrypoint)));
|
|
4448
4620
|
}
|
|
4449
4621
|
|
|
4622
|
+
// Zig entrypoint directory
|
|
4623
|
+
if (config.build.mainProcess === "zig" && config.build.zig?.entrypoint) {
|
|
4624
|
+
watchDirs.add(join(projectRoot, dirname(config.build.zig.entrypoint)));
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4450
4627
|
// View entrypoint directories
|
|
4451
4628
|
if (config.build.views) {
|
|
4452
4629
|
for (const viewConfig of Object.values(config.build.views)) {
|
|
@@ -4787,6 +4964,10 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
4787
4964
|
...defaultConfig.build.bun,
|
|
4788
4965
|
...(loadedConfig?.build?.bun || {}),
|
|
4789
4966
|
},
|
|
4967
|
+
zig: {
|
|
4968
|
+
...defaultConfig.build.zig,
|
|
4969
|
+
...(loadedConfig?.build?.zig || {}),
|
|
4970
|
+
},
|
|
4790
4971
|
},
|
|
4791
4972
|
runtime: {
|
|
4792
4973
|
...defaultConfig.runtime,
|
|
@@ -5084,13 +5265,10 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
|
5084
5265
|
}
|
|
5085
5266
|
|
|
5086
5267
|
// Sign CEF helper apps (they're in the main Frameworks directory, not inside CEF framework)
|
|
5087
|
-
const
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
"bun Helper (Alerts).app",
|
|
5092
|
-
"bun Helper (Renderer).app",
|
|
5093
|
-
];
|
|
5268
|
+
const mainProcess = config.build.mainProcess ?? "bun";
|
|
5269
|
+
const cefHelperApps = getCEFHelperNames(mainProcess).map(
|
|
5270
|
+
(helperName) => `${helperName}.app`,
|
|
5271
|
+
);
|
|
5094
5272
|
|
|
5095
5273
|
for (const helperApp of cefHelperApps) {
|
|
5096
5274
|
const helperPath = join(frameworksPath, helperApp);
|