electrobun 1.18.4-beta.3 → 1.18.4-beta.6

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.
@@ -9,7 +9,7 @@ pub const WindowBlurHandler = *const fn (u32) callconv(.C) void;
9
9
  pub const WindowKeyHandler = *const fn (u32, u32, u32, u32, u32) callconv(.C) void;
10
10
  pub const DecideNavigationHandler = *const fn (u32, [*:0]const u8) callconv(.C) u32;
11
11
  pub const WebviewEventHandler = *const fn (u32, [*:0]const u8, [*:0]const u8) callconv(.C) void;
12
- pub const WebviewPostMessageHandler = *const fn (u32, [*:0]const u8) callconv(.C) u32;
12
+ pub const WebviewPostMessageHandler = *const fn (u32, [*:0]const u8) callconv(.C) void;
13
13
  pub const StatusItemHandler = *const fn (u32, [*:0]const u8) callconv(.C) void;
14
14
  pub const GlobalShortcutHandler = *const fn ([*:0]const u8) callconv(.C) void;
15
15
  pub const QuitRequestedHandler = *const fn () callconv(.C) void;
@@ -99,6 +99,7 @@ pub const WebviewCallbacks = struct {
99
99
  decide_navigation: ?DecideNavigationHandler = null,
100
100
  event: ?WebviewEventHandler = null,
101
101
  event_bridge: ?WebviewPostMessageHandler = null,
102
+ host_bridge: ?WebviewPostMessageHandler = null,
102
103
  bun_bridge: ?WebviewPostMessageHandler = null,
103
104
  internal_bridge: ?WebviewPostMessageHandler = null,
104
105
  };
@@ -600,6 +601,7 @@ pub const Core = struct {
600
601
  const WebviewFindInPageFn = *const fn (u32, [*:0]const u8, bool, bool) callconv(.C) void;
601
602
  const WebviewStopFindFn = *const fn (u32) callconv(.C) void;
602
603
  const SendInternalMessageToWebviewFn = *const fn (u32, [*:0]const u8) callconv(.C) bool;
604
+ const SendHostMessageToWebviewViaTransportFn = *const fn (u32, [*:0]const u8) callconv(.C) bool;
603
605
  const WebviewOpenDevToolsFn = *const fn (u32) callconv(.C) void;
604
606
  const WebviewCloseDevToolsFn = *const fn (u32) callconv(.C) void;
605
607
  const WebviewToggleDevToolsFn = *const fn (u32) callconv(.C) void;
@@ -710,6 +712,7 @@ pub const Core = struct {
710
712
  webview_find_in_page: WebviewFindInPageFn,
711
713
  webview_stop_find: WebviewStopFindFn,
712
714
  send_internal_message_to_webview: SendInternalMessageToWebviewFn,
715
+ send_host_message_to_webview_via_transport: SendHostMessageToWebviewViaTransportFn,
713
716
  webview_open_devtools: WebviewOpenDevToolsFn,
714
717
  webview_close_devtools: WebviewCloseDevToolsFn,
715
718
  webview_toggle_devtools: WebviewToggleDevToolsFn,
@@ -838,6 +841,7 @@ pub const Core = struct {
838
841
  .webview_find_in_page = lib.lookup(WebviewFindInPageFn, "webviewFindInPage") orelse return error.MissingCoreSymbol,
839
842
  .webview_stop_find = lib.lookup(WebviewStopFindFn, "webviewStopFind") orelse return error.MissingCoreSymbol,
840
843
  .send_internal_message_to_webview = lib.lookup(SendInternalMessageToWebviewFn, "sendInternalMessageToWebview") orelse return error.MissingCoreSymbol,
844
+ .send_host_message_to_webview_via_transport = lib.lookup(SendHostMessageToWebviewViaTransportFn, "sendHostMessageToWebviewViaTransport") orelse return error.MissingCoreSymbol,
841
845
  .webview_open_devtools = lib.lookup(WebviewOpenDevToolsFn, "webviewOpenDevTools") orelse return error.MissingCoreSymbol,
842
846
  .webview_close_devtools = lib.lookup(WebviewCloseDevToolsFn, "webviewCloseDevTools") orelse return error.MissingCoreSymbol,
843
847
  .webview_toggle_devtools = lib.lookup(WebviewToggleDevToolsFn, "webviewToggleDevTools") orelse return error.MissingCoreSymbol,
@@ -1150,7 +1154,7 @@ pub const Core = struct {
1150
1154
  options.callbacks.decide_navigation,
1151
1155
  options.callbacks.event,
1152
1156
  options.callbacks.event_bridge,
1153
- options.callbacks.bun_bridge,
1157
+ options.callbacks.host_bridge orelse options.callbacks.bun_bridge,
1154
1158
  options.callbacks.internal_bridge,
1155
1159
  secret_key_z.ptr,
1156
1160
  preload_z.ptr,
@@ -1399,13 +1403,19 @@ pub const Core = struct {
1399
1403
  try self.ensureLastCallSucceeded();
1400
1404
  }
1401
1405
 
1402
- pub fn sendMessageToWebview(self: *Core, webview_id: u32, message: anytype) !void {
1406
+ pub fn sendHostMessageToWebview(self: *Core, webview_id: u32, message: anytype) !void {
1403
1407
  const message_json = try std.json.stringifyAlloc(self.allocator, message, .{});
1404
1408
  defer self.allocator.free(message_json);
1409
+ const message_json_z = try self.dupeZ(message_json);
1410
+ defer self.allocator.free(message_json_z);
1411
+
1412
+ if (self.symbols.send_host_message_to_webview_via_transport(webview_id, message_json_z.ptr)) {
1413
+ return;
1414
+ }
1405
1415
 
1406
1416
  const js = try std.fmt.allocPrint(
1407
1417
  self.allocator,
1408
- "window.__electrobun.receiveMessageFromBun({s});",
1418
+ "window.__electrobun.receiveMessageFromHost({s});",
1409
1419
  .{message_json},
1410
1420
  );
1411
1421
  defer self.allocator.free(js);
@@ -1413,6 +1423,10 @@ pub const Core = struct {
1413
1423
  try self.evaluateJavaScriptWithNoCompletion(webview_id, js);
1414
1424
  }
1415
1425
 
1426
+ pub fn sendMessageToWebview(self: *Core, webview_id: u32, message: anytype) !void {
1427
+ try self.sendHostMessageToWebview(webview_id, message);
1428
+ }
1429
+
1416
1430
  pub fn sendInternalMessageToWebview(self: *Core, webview_id: u32, message: anytype) !void {
1417
1431
  const message_json = try std.json.stringifyAlloc(self.allocator, message, .{});
1418
1432
  defer self.allocator.free(message_json);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrobun",
3
- "version": "1.18.4-beta.3",
3
+ "version": "1.18.4-beta.6",
4
4
  "description": "Build ultra fast, tiny, and cross-platform desktop apps with Typescript.",
5
5
  "license": "MIT",
6
6
  "author": "Blackboard Technologies Inc.",
package/src/cli/index.ts CHANGED
@@ -1686,6 +1686,24 @@ const defaultConfig = {
1686
1686
  path?: string;
1687
1687
  [key: string]: unknown;
1688
1688
  }>;
1689
+ slateUIs?: Record<string, {
1690
+ name?: string;
1691
+ entrypoint?: string;
1692
+ path?: string;
1693
+ [key: string]: unknown;
1694
+ }>;
1695
+ contributions?: {
1696
+ fileActivators?: Array<{
1697
+ baseName?: string;
1698
+ nodeType?: "file" | "dir" | "any";
1699
+ slate: {
1700
+ type: string;
1701
+ name?: string;
1702
+ icon?: string;
1703
+ config?: Record<string, unknown>;
1704
+ };
1705
+ }>;
1706
+ };
1689
1707
  carrotOnly?: boolean;
1690
1708
  } | undefined,
1691
1709
  },
@@ -2532,7 +2550,7 @@ Categories=Utility;Application;
2532
2550
 
2533
2551
  // refresh build folder
2534
2552
  if (existsSync(buildFolder)) {
2535
- rmSync(buildFolder, { recursive: true });
2553
+ rmSync(buildFolder, { recursive: true, force: true });
2536
2554
  }
2537
2555
  mkdirSync(buildFolder, { recursive: true });
2538
2556
 
@@ -3572,6 +3590,55 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
3572
3590
  }
3573
3591
  }
3574
3592
 
3593
+ // Build slate UIs if configured.
3594
+ // slateUIs mirrors remoteUIs, but points at an ESM module entry file instead of an HTML page.
3595
+ const resolvedSlateUIs: Record<string, { name: string; path: string }> = {};
3596
+ if (carrotConfig.slateUIs) {
3597
+ for (const slateUIName in carrotConfig.slateUIs) {
3598
+ const slateUIConfig = carrotConfig.slateUIs[slateUIName]!;
3599
+ const label = slateUIConfig.name || slateUIName;
3600
+
3601
+ if (slateUIConfig.entrypoint) {
3602
+ const slateUISource = join(projectRoot, slateUIConfig.entrypoint);
3603
+ if (!existsSync(slateUISource)) {
3604
+ console.error(`Slate UI entrypoint not found: ${slateUISource}`);
3605
+ continue;
3606
+ }
3607
+ const slateUIDestFolder = join(carrotBuildDir, "slate-ui", slateUIName);
3608
+ mkdirSync(slateUIDestFolder, { recursive: true });
3609
+
3610
+ const { entrypoint: _entrypoint, name: _name, path: _path, ...slateUIBuildOptions } = slateUIConfig;
3611
+ const slateUIBuildResult = await Bun.build({
3612
+ ...slateUIBuildOptions,
3613
+ entrypoints: [slateUISource],
3614
+ outdir: slateUIDestFolder,
3615
+ target: "browser",
3616
+ format: "esm",
3617
+ });
3618
+
3619
+ if (!slateUIBuildResult.success) {
3620
+ console.error(`Failed to build slate UI: ${slateUIName}`);
3621
+ printBuildLogs(slateUIBuildResult.logs);
3622
+ continue;
3623
+ }
3624
+
3625
+ resolvedSlateUIs[slateUIName] = {
3626
+ name: label,
3627
+ path: `slate-ui/${slateUIName}/index.js`,
3628
+ };
3629
+ } else if (slateUIConfig.path) {
3630
+ resolvedSlateUIs[slateUIName] = {
3631
+ name: label,
3632
+ path: slateUIConfig.path,
3633
+ };
3634
+ } else {
3635
+ console.warn(
3636
+ `Slate UI "${slateUIName}" has neither entrypoint nor path; skipping.`,
3637
+ );
3638
+ }
3639
+ }
3640
+ }
3641
+
3575
3642
  // Write carrot.json manifest
3576
3643
  const carrotManifest = {
3577
3644
  id: carrotConfig.id,
@@ -3589,9 +3656,15 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
3589
3656
  : spec,
3590
3657
  ]),
3591
3658
  ),
3659
+ contributions:
3660
+ carrotConfig.contributions &&
3661
+ Object.keys(carrotConfig.contributions).length > 0
3662
+ ? carrotConfig.contributions
3663
+ : undefined,
3592
3664
  worker: { relativePath: "worker.js" },
3593
3665
  view: existsSync(viewsSrc) ? { relativePath: "views/index.html" } : undefined,
3594
3666
  remoteUIs: Object.keys(resolvedRemoteUIs).length > 0 ? resolvedRemoteUIs : undefined,
3667
+ slateUIs: Object.keys(resolvedSlateUIs).length > 0 ? resolvedSlateUIs : undefined,
3595
3668
  };
3596
3669
  writeFileSync(
3597
3670
  join(carrotBuildDir, "carrot.json"),
@@ -4703,17 +4776,37 @@ usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
4703
4776
  );
4704
4777
 
4705
4778
  function shouldIgnore(fullPath: string): boolean {
4779
+ const resolvedFullPath = path.resolve(fullPath);
4780
+ const pathSegments = resolvedFullPath.split(path.sep).filter(Boolean);
4781
+ const genericIgnoredSegments = new Set([
4782
+ "node_modules",
4783
+ path.basename(buildDir),
4784
+ path.basename(artifactDir),
4785
+ ".electrobun-cache",
4786
+ ]);
4787
+ if (pathSegments.some((segment) => genericIgnoredSegments.has(segment))) {
4788
+ return true;
4789
+ }
4706
4790
  // Check built-in ignore dirs
4707
4791
  if (
4708
4792
  ignoreDirs.some(
4709
- (ignored) =>
4710
- fullPath.startsWith(ignored + "/") || fullPath === ignored,
4793
+ (ignored) => {
4794
+ const relativeToIgnored = path.relative(ignored, resolvedFullPath);
4795
+ return (
4796
+ relativeToIgnored === "" ||
4797
+ (!relativeToIgnored.startsWith("..") &&
4798
+ !path.isAbsolute(relativeToIgnored))
4799
+ );
4800
+ },
4711
4801
  )
4712
4802
  ) {
4713
4803
  return true;
4714
4804
  }
4715
4805
  // Check user-configured watchIgnore globs (match against project-relative path)
4716
- const relativePath = fullPath.replace(projectRoot + "/", "");
4806
+ const relativePath = path
4807
+ .relative(projectRoot, resolvedFullPath)
4808
+ .split(path.sep)
4809
+ .join("/");
4717
4810
  if (ignoreGlobs.some((glob) => glob.match(relativePath))) {
4718
4811
  return true;
4719
4812
  }