bunite-core 0.17.0 → 0.17.2

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.
@@ -62,7 +62,7 @@ export function removeSurfacesForHostView(hostViewId: number) {
62
62
  for (const surfaceId of Array.from(ids)) {
63
63
  const record = surfaces.get(surfaceId);
64
64
  if (!record) continue;
65
- untrackSurface(surfaceId); // fires disposeHooks
65
+ untrackSurface(surfaceId); // fires disposeHooks
66
66
  record.view.remove();
67
67
  }
68
68
  }
@@ -38,7 +38,15 @@ export interface ResolvedKey {
38
38
  /** Maps a DOM `KeyboardEvent.key` value to backend-neutral identifiers. */
39
39
  export function resolveKey(domKey: string): ResolvedKey {
40
40
  if (domKey.length === 0) {
41
- return { windowsVkCode: 0, macKeyCode: 0, key: "", code: "", character: "", extended: false, location: 0 };
41
+ return {
42
+ windowsVkCode: 0,
43
+ macKeyCode: 0,
44
+ key: "",
45
+ code: "",
46
+ character: "",
47
+ extended: false,
48
+ location: 0,
49
+ };
42
50
  }
43
51
 
44
52
  // Named key (Enter, Tab, ArrowLeft …).
@@ -61,8 +69,8 @@ export function resolveKey(domKey: string): ResolvedKey {
61
69
  if ([...domKey].length === 1) {
62
70
  const cp = domKey.codePointAt(0)!;
63
71
  // ASCII A-Z / a-z → matching Win VK + mac keyCode + DOM code "KeyX".
64
- if ((cp >= 0x41 && cp <= 0x5A) || (cp >= 0x61 && cp <= 0x7A)) {
65
- const upper = cp & ~0x20; // strip lowercase bit
72
+ if ((cp >= 0x41 && cp <= 0x5a) || (cp >= 0x61 && cp <= 0x7a)) {
73
+ const upper = cp & ~0x20; // strip lowercase bit
66
74
  return {
67
75
  windowsVkCode: upper,
68
76
  macKeyCode: MAC_KEY_LETTER[upper - 0x41],
@@ -86,11 +94,27 @@ export function resolveKey(domKey: string): ResolvedKey {
86
94
  };
87
95
  }
88
96
  // Other printable codepoint — char event only, no virtual key.
89
- return { windowsVkCode: 0, macKeyCode: 0, key: domKey, code: "", character: domKey, extended: false, location: 0 };
97
+ return {
98
+ windowsVkCode: 0,
99
+ macKeyCode: 0,
100
+ key: domKey,
101
+ code: "",
102
+ character: domKey,
103
+ extended: false,
104
+ location: 0,
105
+ };
90
106
  }
91
107
 
92
108
  // Multi-codepoint string we don't recognise as a named key — pass-through.
93
- return { windowsVkCode: 0, macKeyCode: 0, key: domKey, code: "", character: "", extended: false, location: 0 };
109
+ return {
110
+ windowsVkCode: 0,
111
+ macKeyCode: 0,
112
+ key: domKey,
113
+ code: "",
114
+ character: "",
115
+ extended: false,
116
+ location: 0,
117
+ };
94
118
  }
95
119
 
96
120
  // Win32 VK_* + Quartz Event Services kVK_* + DOM code + literal character +
@@ -99,49 +123,54 @@ export function resolveKey(domKey: string): ResolvedKey {
99
123
  // from LPARAM scancode + extended bit. Sources:
100
124
  // learn.microsoft.com/windows/win32/inputdev/virtual-key-codes
101
125
  // chromium/ui/events/keycodes/dom/keycode_converter_data.inc
102
- type NamedKey = { win: number; mac: number; code: string; character?: string; ext?: true; loc?: 1 | 2 | 3 };
126
+ type NamedKey = {
127
+ win: number;
128
+ mac: number;
129
+ code: string;
130
+ character?: string;
131
+ ext?: true;
132
+ loc?: 1 | 2 | 3;
133
+ };
103
134
  const NAMED_KEYS: Record<string, NamedKey> = {
104
- Backspace: { win: 0x08, mac: 0x33, code: "Backspace" },
105
- Tab: { win: 0x09, mac: 0x30, code: "Tab", character: "\t" },
106
- Enter: { win: 0x0D, mac: 0x24, code: "Enter", character: "\r" },
107
- NumpadEnter: { win: 0x0D, mac: 0x4C, code: "NumpadEnter", character: "\r", ext: true, loc: 3 },
108
- Escape: { win: 0x1B, mac: 0x35, code: "Escape" },
109
- " ": { win: 0x20, mac: 0x31, code: "Space", character: " " },
110
- Space: { win: 0x20, mac: 0x31, code: "Space", character: " " },
111
- PageUp: { win: 0x21, mac: 0x74, code: "PageUp", ext: true },
112
- PageDown: { win: 0x22, mac: 0x79, code: "PageDown", ext: true },
113
- End: { win: 0x23, mac: 0x77, code: "End", ext: true },
114
- Home: { win: 0x24, mac: 0x73, code: "Home", ext: true },
115
- ArrowLeft: { win: 0x25, mac: 0x7B, code: "ArrowLeft", ext: true },
116
- ArrowUp: { win: 0x26, mac: 0x7E, code: "ArrowUp", ext: true },
117
- ArrowRight: { win: 0x27, mac: 0x7C, code: "ArrowRight", ext: true },
118
- ArrowDown: { win: 0x28, mac: 0x7D, code: "ArrowDown", ext: true },
119
- Insert: { win: 0x2D, mac: 0x72, code: "Insert", ext: true },
120
- Delete: { win: 0x2E, mac: 0x75, code: "Delete", ext: true },
121
- Meta: { win: 0x5B, mac: 0x37, code: "MetaLeft", ext: true },
122
- ContextMenu: { win: 0x5D, mac: 0x6E, code: "ContextMenu", ext: true },
123
- F1: { win: 0x70, mac: 0x7A, code: "F1" },
124
- F2: { win: 0x71, mac: 0x78, code: "F2" },
125
- F3: { win: 0x72, mac: 0x63, code: "F3" },
126
- F4: { win: 0x73, mac: 0x76, code: "F4" },
127
- F5: { win: 0x74, mac: 0x60, code: "F5" },
128
- F6: { win: 0x75, mac: 0x61, code: "F6" },
129
- F7: { win: 0x76, mac: 0x62, code: "F7" },
130
- F8: { win: 0x77, mac: 0x64, code: "F8" },
131
- F9: { win: 0x78, mac: 0x65, code: "F9" },
132
- F10: { win: 0x79, mac: 0x6D, code: "F10" },
133
- F11: { win: 0x7A, mac: 0x67, code: "F11" },
134
- F12: { win: 0x7B, mac: 0x6F, code: "F12" },
135
+ Backspace: { win: 0x08, mac: 0x33, code: "Backspace" },
136
+ Tab: { win: 0x09, mac: 0x30, code: "Tab", character: "\t" },
137
+ Enter: { win: 0x0d, mac: 0x24, code: "Enter", character: "\r" },
138
+ NumpadEnter: { win: 0x0d, mac: 0x4c, code: "NumpadEnter", character: "\r", ext: true, loc: 3 },
139
+ Escape: { win: 0x1b, mac: 0x35, code: "Escape" },
140
+ " ": { win: 0x20, mac: 0x31, code: "Space", character: " " },
141
+ Space: { win: 0x20, mac: 0x31, code: "Space", character: " " },
142
+ PageUp: { win: 0x21, mac: 0x74, code: "PageUp", ext: true },
143
+ PageDown: { win: 0x22, mac: 0x79, code: "PageDown", ext: true },
144
+ End: { win: 0x23, mac: 0x77, code: "End", ext: true },
145
+ Home: { win: 0x24, mac: 0x73, code: "Home", ext: true },
146
+ ArrowLeft: { win: 0x25, mac: 0x7b, code: "ArrowLeft", ext: true },
147
+ ArrowUp: { win: 0x26, mac: 0x7e, code: "ArrowUp", ext: true },
148
+ ArrowRight: { win: 0x27, mac: 0x7c, code: "ArrowRight", ext: true },
149
+ ArrowDown: { win: 0x28, mac: 0x7d, code: "ArrowDown", ext: true },
150
+ Insert: { win: 0x2d, mac: 0x72, code: "Insert", ext: true },
151
+ Delete: { win: 0x2e, mac: 0x75, code: "Delete", ext: true },
152
+ Meta: { win: 0x5b, mac: 0x37, code: "MetaLeft", ext: true },
153
+ ContextMenu: { win: 0x5d, mac: 0x6e, code: "ContextMenu", ext: true },
154
+ F1: { win: 0x70, mac: 0x7a, code: "F1" },
155
+ F2: { win: 0x71, mac: 0x78, code: "F2" },
156
+ F3: { win: 0x72, mac: 0x63, code: "F3" },
157
+ F4: { win: 0x73, mac: 0x76, code: "F4" },
158
+ F5: { win: 0x74, mac: 0x60, code: "F5" },
159
+ F6: { win: 0x75, mac: 0x61, code: "F6" },
160
+ F7: { win: 0x76, mac: 0x62, code: "F7" },
161
+ F8: { win: 0x77, mac: 0x64, code: "F8" },
162
+ F9: { win: 0x78, mac: 0x65, code: "F9" },
163
+ F10: { win: 0x79, mac: 0x6d, code: "F10" },
164
+ F11: { win: 0x7a, mac: 0x67, code: "F11" },
165
+ F12: { win: 0x7b, mac: 0x6f, code: "F12" },
135
166
  };
136
167
 
137
168
  // US keyboard layout — Quartz hardware key code per ASCII letter (A → 0x00, …, Z → 0x06).
138
169
  const MAC_KEY_LETTER = [
139
170
  // A B C D E F G H I J K L M
140
- 0x00, 0x0B, 0x08, 0x02, 0x0E, 0x03, 0x05, 0x04, 0x22, 0x26, 0x28, 0x25, 0x2E,
171
+ 0x00, 0x0b, 0x08, 0x02, 0x0e, 0x03, 0x05, 0x04, 0x22, 0x26, 0x28, 0x25, 0x2e,
141
172
  // N O P Q R S T U V W X Y Z
142
- 0x2D, 0x1F, 0x23, 0x0C, 0x0F, 0x01, 0x11, 0x20, 0x09, 0x0D, 0x07, 0x10, 0x06,
173
+ 0x2d, 0x1f, 0x23, 0x0c, 0x0f, 0x01, 0x11, 0x20, 0x09, 0x0d, 0x07, 0x10, 0x06,
143
174
  ];
144
175
  // US keyboard layout — Quartz hardware key code per digit (0 → 0x1D, 1 → 0x12 …).
145
- const MAC_KEY_DIGIT = [
146
- 0x1D, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, 0x1A, 0x1C, 0x19,
147
- ];
176
+ const MAC_KEY_DIGIT = [0x1d, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, 0x1a, 0x1c, 0x19];
@@ -62,7 +62,11 @@ export function acquireSingleInstanceLock(key: string): SingleInstanceLock {
62
62
  // Verify ownership before unlinking — guards against deleting a lockfile
63
63
  // that has been reclaimed by another process if our exit was delayed.
64
64
  if (readHolderPid(path) === process.pid) {
65
- try { unlinkSync(path); } catch { /* already gone */ }
65
+ try {
66
+ unlinkSync(path);
67
+ } catch {
68
+ /* already gone */
69
+ }
66
70
  }
67
71
  process.off("exit", release);
68
72
  };
@@ -82,7 +86,11 @@ export function acquireSingleInstanceLock(key: string): SingleInstanceLock {
82
86
  return { acquired: false, holderPid };
83
87
  }
84
88
  // Stale: holder is dead. Drop and retry once.
85
- try { unlinkSync(path); } catch { /* lost the race; loop retries */ }
89
+ try {
90
+ unlinkSync(path);
91
+ } catch {
92
+ /* lost the race; loop retries */
93
+ }
86
94
  }
87
95
  }
88
96
 
@@ -1,9 +1,12 @@
1
- import { BrowserWindow } from "./BrowserWindow";
2
1
  import {
3
- BrowserWindowCap, WindowCap, IpcError,
4
- type ImplOf, type WindowState,
2
+ BrowserWindowCap,
3
+ type ImplOf,
4
+ IpcError,
5
+ type WindowCap,
6
+ type WindowState,
5
7
  } from "../../rpc/index";
6
8
  import { Stream } from "../../rpc/stream";
9
+ import { BrowserWindow } from "./BrowserWindow";
7
10
 
8
11
  function browserWindowImpl(win: BrowserWindow): ImplOf<typeof BrowserWindowCap> {
9
12
  return {
@@ -20,22 +23,27 @@ function browserWindowImpl(win: BrowserWindow): ImplOf<typeof BrowserWindowCap>
20
23
  toggleMaximize: () => win.toggleMaximize(),
21
24
  beginMoveDrag: () => win.beginMoveDrag(),
22
25
  getState: () => win.getState(),
23
- stateWatch: () => Stream.from<WindowState>((emit, signal) => {
24
- let last = "";
25
- const push = () => {
26
- const s = win.getState();
27
- const key = `${s.maximized}|${s.minimized}|${s.focused}`;
28
- if (key === last) return;
29
- last = key;
30
- emit(s);
31
- };
32
- push(); // initial snapshot
33
- const offs = [
34
- win.on("focus", push), win.on("blur", push),
35
- win.on("move", push), win.on("resize", push),
36
- ];
37
- signal.addEventListener("abort", () => { for (const off of offs) off(); });
38
- }),
26
+ stateWatch: () =>
27
+ Stream.from<WindowState>((emit, signal) => {
28
+ let last = "";
29
+ const push = () => {
30
+ const s = win.getState();
31
+ const key = `${s.maximized}|${s.minimized}|${s.focused}`;
32
+ if (key === last) return;
33
+ last = key;
34
+ emit(s);
35
+ };
36
+ push(); // initial snapshot
37
+ const offs = [
38
+ win.on("focus", push),
39
+ win.on("blur", push),
40
+ win.on("move", push),
41
+ win.on("resize", push),
42
+ ];
43
+ signal.addEventListener("abort", () => {
44
+ for (const off of offs) off();
45
+ });
46
+ }),
39
47
  };
40
48
  }
41
49
 
@@ -51,8 +59,15 @@ export function createWindowCapImpl(viewId: number): ImplOf<typeof WindowCap> {
51
59
  return {
52
60
  create: ({ url, title, bounds, label }, ctx) => {
53
61
  const win = new BrowserWindow({
54
- url, title, label,
55
- frame: { x: bounds?.x ?? 80, y: bounds?.y ?? 80, width: bounds?.w ?? 1280, height: bounds?.h ?? 900 },
62
+ url,
63
+ title,
64
+ label,
65
+ frame: {
66
+ x: bounds?.x ?? 80,
67
+ y: bounds?.y ?? 80,
68
+ width: bounds?.w ?? 1280,
69
+ height: bounds?.h ?? 900,
70
+ },
56
71
  });
57
72
  return ctx.exportCap(BrowserWindowCap, browserWindowImpl(win));
58
73
  },
@@ -63,7 +78,11 @@ export function createWindowCapImpl(viewId: number): ImplOf<typeof WindowCap> {
63
78
  if (!win) throw new IpcError({ code: "not_found", message: "no window for this view" });
64
79
  return ctx.exportCap(BrowserWindowCap, browserWindowImpl(win));
65
80
  },
66
- focus: (args) => { resolve(args)?.focus(); },
67
- close: (args) => { resolve(args)?.close(); },
81
+ focus: (args) => {
82
+ resolve(args)?.focus();
83
+ },
84
+ close: (args) => {
85
+ resolve(args)?.close();
86
+ },
68
87
  };
69
88
  }
@@ -10,7 +10,12 @@ const HEADER_LENGTH = 1 + IV_LENGTH;
10
10
  export async function createEncryptedPipe(base: BytesPipe, rawKey: Uint8Array): Promise<BytesPipe> {
11
11
  let downstream: ((bytes: Uint8Array) => void) | undefined;
12
12
  let closed = false;
13
- const closeOnce = () => { if (!closed) { closed = true; base.close(); } };
13
+ const closeOnce = () => {
14
+ if (!closed) {
15
+ closed = true;
16
+ base.close();
17
+ }
18
+ };
14
19
 
15
20
  base.setReceive((frame) => {
16
21
  if (closed) return;
@@ -56,7 +61,11 @@ export async function createEncryptedPipe(base: BytesPipe, rawKey: Uint8Array):
56
61
  closeOnce();
57
62
  }
58
63
  },
59
- setReceive(handler) { downstream = handler; },
60
- close() { closeOnce(); },
64
+ setReceive(handler) {
65
+ downstream = handler;
66
+ },
67
+ close() {
68
+ closeOnce();
69
+ },
61
70
  };
62
71
  }
@@ -3,5 +3,5 @@ import { BuniteEvent } from "./event";
3
3
  export default {
4
4
  beforeQuit: (data: Record<string, unknown>) =>
5
5
  new BuniteEvent<Record<string, unknown>, { allow?: boolean }>("before-quit", data),
6
- allWindowsClosed: () => new BuniteEvent("all-windows-closed", {})
6
+ allWindowsClosed: () => new BuniteEvent("all-windows-closed", {}),
7
7
  };
@@ -1,8 +1,8 @@
1
1
  import EventEmitter from "node:events";
2
- import { BuniteEvent } from "./event";
3
2
  import appEvents from "./appEvents";
4
- import windowEvents from "./windowEvents";
3
+ import type { BuniteEvent } from "./event";
5
4
  import webviewEvents from "./webviewEvents";
5
+ import windowEvents from "./windowEvents";
6
6
 
7
7
  class BuniteEventEmitter extends EventEmitter {
8
8
  emitEvent(event: BuniteEvent, specifier?: string | number) {
@@ -14,14 +14,14 @@ class BuniteEventEmitter extends EventEmitter {
14
14
 
15
15
  events = {
16
16
  app: {
17
- ...appEvents
17
+ ...appEvents,
18
18
  },
19
19
  window: {
20
- ...windowEvents
20
+ ...windowEvents,
21
21
  },
22
22
  webview: {
23
- ...webviewEvents
24
- }
23
+ ...webviewEvents,
24
+ },
25
25
  };
26
26
  }
27
27
 
@@ -12,10 +12,17 @@ export default {
12
12
  loadStart: (data: { detail: string }) => new BuniteEvent("load-start", data),
13
13
  loadFinish: (data: { detail: string }) => new BuniteEvent("load-finish", data),
14
14
  loadFail: (data: { url: string; reason?: string }) => new BuniteEvent("load-fail", data),
15
- dialog: (data: { requestId: number; kind: "alert" | "confirm" | "prompt" | "beforeunload"; message: string; defaultPrompt?: string }) =>
16
- new BuniteEvent("dialog", data),
17
- consoleMessage: (data: { level: "log" | "warn" | "error" | "info" | "debug"; args: string[]; ts: number }) =>
18
- new BuniteEvent("console-message", data),
15
+ dialog: (data: {
16
+ requestId: number;
17
+ kind: "alert" | "confirm" | "prompt" | "beforeunload";
18
+ message: string;
19
+ defaultPrompt?: string;
20
+ }) => new BuniteEvent("dialog", data),
21
+ consoleMessage: (data: {
22
+ level: "log" | "warn" | "error" | "info" | "debug";
23
+ args: string[];
24
+ ts: number;
25
+ }) => new BuniteEvent("console-message", data),
19
26
  downloadEvent: (data: {
20
27
  kind: "started" | "progress" | "completed" | "failed" | "blocked";
21
28
  id: string;
@@ -16,6 +16,5 @@ export default {
16
16
  height: number;
17
17
  maximized: boolean;
18
18
  minimized: boolean;
19
- }) =>
20
- new BuniteEvent("resize", data)
19
+ }) => new BuniteEvent("resize", data),
21
20
  };
package/src/host/index.ts CHANGED
@@ -1,29 +1,21 @@
1
1
  import { AppRuntime } from "./core/App";
2
- import { BrowserWindow, type WindowOptionsType } from "./core/BrowserWindow";
3
2
  import { BrowserView, type BrowserViewOptions } from "./core/BrowserView";
3
+ import { BrowserWindow, type WindowOptionsType } from "./core/BrowserWindow";
4
+ import { acquireSingleInstanceLock, type SingleInstanceLock } from "./core/singleInstanceLock";
5
+ import type { BuniteEvent } from "./events/event";
4
6
  import { buniteEventEmitter } from "./events/eventEmitter";
5
- import { BuniteEvent } from "./events/event";
7
+ import { type LogLevel, log } from "./log";
6
8
  import { completePermissionRequest } from "./native";
7
- import { acquireSingleInstanceLock, type SingleInstanceLock } from "./core/singleInstanceLock";
8
- import { log, type LogLevel } from "./log";
9
9
 
10
+ export type { ServeWebOptions, WebRpcMount, WsData } from "./serveWeb";
10
11
  export { serveWeb } from "./serveWeb";
11
- export type { WebRpcMount, WsData, ServeWebOptions } from "./serveWeb";
12
-
12
+ export type { BrowserViewOptions, BuniteEvent, LogLevel, SingleInstanceLock, WindowOptionsType };
13
13
  export {
14
- acquireSingleInstanceLock,
15
14
  AppRuntime,
16
- BrowserWindow,
15
+ acquireSingleInstanceLock,
17
16
  BrowserView,
17
+ BrowserWindow,
18
18
  buniteEventEmitter,
19
19
  completePermissionRequest,
20
- log
21
- };
22
-
23
- export type {
24
- LogLevel,
25
- BuniteEvent,
26
- BrowserViewOptions,
27
- SingleInstanceLock,
28
- WindowOptionsType
20
+ log,
29
21
  };
package/src/host/log.ts CHANGED
@@ -5,12 +5,14 @@ const levels: Record<LogLevel, number> = {
5
5
  info: 1,
6
6
  warn: 2,
7
7
  error: 3,
8
- silent: 4
8
+ silent: 4,
9
9
  };
10
10
 
11
11
  function initialLevel(): LogLevel {
12
- const v = (typeof process !== "undefined" ? process.env?.BUNITE_LOG_LEVEL : undefined);
13
- return v === "debug" || v === "info" || v === "warn" || v === "error" || v === "silent" ? v : "warn";
12
+ const v = typeof process !== "undefined" ? process.env?.BUNITE_LOG_LEVEL : undefined;
13
+ return v === "debug" || v === "info" || v === "warn" || v === "error" || v === "silent"
14
+ ? v
15
+ : "warn";
14
16
  }
15
17
 
16
18
  let currentLevel: LogLevel = initialLevel();
@@ -41,5 +43,5 @@ export const log = {
41
43
  },
42
44
  error(...args: unknown[]) {
43
45
  if (shouldLog("error")) console.error("[bunite]", ...args);
44
- }
46
+ },
45
47
  };