murasaki 0.4.0 → 0.4.1

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/dist/dev.js CHANGED
@@ -1,35 +1,23 @@
1
- // src/dev.tsx
2
- // Murasaki dev runner Next.js-like file-based routing without Next.js.
3
- //
4
- // Reads the consumer's src/ directory:
5
- // src/layout.tsx (optional, can export `metadata`)
6
- // src/app.tsx (required)
7
- // src/globals.css (optional, auto-injected)
8
- //
9
- // Renders <Layout><App /></Layout> with React, ships HTML to the WebView,
10
- // and reloads in place on file change.
11
- import { printBanner, printBye, printOpened, printReady, printShortcuts, printStarting, } from "./cli/log.js";
1
+ // src/dev.tsx — boot entry for `murasaki dev`.
2
+ import { printBanner, printBye, printReady, printStarting, } from "./cli/log.js";
12
3
  import { setupHmr } from "./runtime/hmr.js";
13
- import { setupShortcuts, teardownStdin } from "./runtime/shortcuts.js";
4
+ import { setupShortcuts } from "./runtime/shortcuts.js";
14
5
  import { closeWindow, exitApp, getConfig, openWindow, reloadWindow, runApp, } from "./runtime/window.js";
15
6
  const startAt = Date.now();
16
- // Boot: render once (applies metadata) → banner → ready
17
7
  await openWindow();
18
8
  printBanner(getConfig().title, getConfig());
19
- printShortcuts();
20
9
  printStarting();
21
10
  printReady(Date.now() - startAt);
22
11
  setupShortcuts({
23
12
  onOpen: () => {
24
- void openWindow().then(printOpened);
13
+ void openWindow();
25
14
  },
26
15
  onRestart: () => {
27
16
  closeWindow();
28
- void openWindow().then(printOpened);
17
+ void openWindow();
29
18
  },
30
19
  onQuit: () => {
31
20
  printBye();
32
- teardownStdin();
33
21
  exitApp();
34
22
  process.exit(0);
35
23
  },
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.tsx"],"names":[],"mappings":"AAAA,cAAc;AACd,yEAAyE;AACzE,EAAE;AACF,uCAAuC;AACvC,uDAAuD;AACvD,gCAAgC;AAChC,+CAA+C;AAC/C,EAAE;AACF,0EAA0E;AAC1E,uCAAuC;AAEvC,OAAO,EACL,WAAW,EACX,QAAQ,EACR,WAAW,EACX,UAAU,EACV,cAAc,EACd,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EACL,WAAW,EACX,OAAO,EACP,SAAS,EACT,UAAU,EACV,YAAY,EACZ,MAAM,GACP,MAAM,qBAAqB,CAAA;AAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;AAE1B,wDAAwD;AACxD,MAAM,UAAU,EAAE,CAAA;AAClB,WAAW,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;AAC3C,cAAc,EAAE,CAAA;AAChB,aAAa,EAAE,CAAA;AACf,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAA;AAEhC,cAAc,CAAC;IACb,MAAM,EAAE,GAAG,EAAE;QACX,KAAK,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACrC,CAAC;IACD,SAAS,EAAE,GAAG,EAAE;QACd,WAAW,EAAE,CAAA;QACb,KAAK,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACrC,CAAC;IACD,MAAM,EAAE,GAAG,EAAE;QACX,QAAQ,EAAE,CAAA;QACV,aAAa,EAAE,CAAA;QACf,OAAO,EAAE,CAAA;QACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;CACF,CAAC,CAAA;AAEF,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;IAChB,KAAK,YAAY,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC,CAAC,CAAA;AAEF,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.tsx"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,OAAO,EACL,WAAW,EACX,QAAQ,EACR,UAAU,EACV,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EACL,WAAW,EACX,OAAO,EACP,SAAS,EACT,UAAU,EACV,YAAY,EACZ,MAAM,GACP,MAAM,qBAAqB,CAAA;AAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;AAE1B,MAAM,UAAU,EAAE,CAAA;AAClB,WAAW,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;AAC3C,aAAa,EAAE,CAAA;AACf,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAA;AAEhC,cAAc,CAAC;IACb,MAAM,EAAE,GAAG,EAAE;QACX,KAAK,UAAU,EAAE,CAAA;IACnB,CAAC;IACD,SAAS,EAAE,GAAG,EAAE;QACd,WAAW,EAAE,CAAA;QACb,KAAK,UAAU,EAAE,CAAA;IACnB,CAAC;IACD,MAAM,EAAE,GAAG,EAAE;QACX,QAAQ,EAAE,CAAA;QACV,OAAO,EAAE,CAAA;QACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;CACF,CAAC,CAAA;AAEF,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;IAChB,KAAK,YAAY,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC,CAAC,CAAA;AAEF,MAAM,EAAE,CAAA"}
@@ -1,2 +1,3 @@
1
1
  export declare function setupHmr(onChange: (filename: string) => void): void;
2
+ export declare function teardownHmr(): void;
2
3
  //# sourceMappingURL=hmr.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../../src/runtime/hmr.ts"],"names":[],"mappings":"AAMA,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAmBnE"}
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../../src/runtime/hmr.ts"],"names":[],"mappings":"AAeA,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAuBnE;AAED,wBAAgB,WAAW,IAAI,IAAI,CAOlC"}
@@ -1,7 +1,15 @@
1
1
  // File watcher for src/ — debounces multi-event saves and triggers reload.
2
+ //
3
+ // macOS note: Node's fs.watch wraps FSEvents, which keeps the libuv loop
4
+ // alive AND, observed in practice, somehow blocks the OS close button on
5
+ // the webview window from completing. We:
6
+ // 1. unref() the watcher so it doesn't prop the process up on its own
7
+ // 2. close() it explicitly on app/window close (via teardown)
8
+ // That keeps HMR responsive while letting the red close button work.
2
9
  import { existsSync, watch } from 'node:fs';
3
10
  import { printHint } from "../cli/log.js";
4
11
  import { SRC_DIR } from "../env.js";
12
+ let activeWatcher = null;
5
13
  export function setupHmr(onChange) {
6
14
  if (!existsSync(SRC_DIR)) {
7
15
  printHint('src/ directory not found — nothing to watch');
@@ -10,7 +18,7 @@ export function setupHmr(onChange) {
10
18
  let debounce = null;
11
19
  let lastFile = '';
12
20
  try {
13
- watch(SRC_DIR, { recursive: true }, (_event, filename) => {
21
+ const w = watch(SRC_DIR, { recursive: true }, (_event, filename) => {
14
22
  if (!filename)
15
23
  return;
16
24
  if (debounce)
@@ -20,9 +28,22 @@ export function setupHmr(onChange) {
20
28
  onChange(lastFile);
21
29
  }, 80);
22
30
  });
31
+ // Don't let the watcher alone keep the process alive — the Cocoa main
32
+ // loop in @webviewjs/webview is the real keep-alive.
33
+ w.unref?.();
34
+ activeWatcher = w;
23
35
  }
24
36
  catch (e) {
25
37
  printHint(`HMR watcher failed: ${e.message}`);
26
38
  }
27
39
  }
40
+ export function teardownHmr() {
41
+ if (activeWatcher) {
42
+ try {
43
+ activeWatcher.close();
44
+ }
45
+ catch { }
46
+ activeWatcher = null;
47
+ }
48
+ }
28
49
  //# sourceMappingURL=hmr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../../src/runtime/hmr.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAE3E,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,MAAM,UAAU,QAAQ,CAAC,QAAoC;IAC3D,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,SAAS,CAAC,6CAA6C,CAAC,CAAA;QACxD,OAAM;IACR,CAAC;IACD,IAAI,QAAQ,GAA0B,IAAI,CAAA;IAC1C,IAAI,QAAQ,GAAG,EAAE,CAAA;IACjB,IAAI,CAAC;QACH,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YACvD,IAAI,CAAC,QAAQ;gBAAE,OAAM;YACrB,IAAI,QAAQ;gBAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;YACpC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAA;YAC9B,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;gBACzB,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACpB,CAAC,EAAE,EAAE,CAAC,CAAA;QACR,CAAC,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,SAAS,CAAC,uBAAuB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;IAC/C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../../src/runtime/hmr.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,0CAA0C;AAC1C,wEAAwE;AACxE,gEAAgE;AAChE,qEAAqE;AAErE,OAAO,EAAkB,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,IAAI,aAAa,GAAqB,IAAI,CAAA;AAE1C,MAAM,UAAU,QAAQ,CAAC,QAAoC;IAC3D,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,SAAS,CAAC,6CAA6C,CAAC,CAAA;QACxD,OAAM;IACR,CAAC;IACD,IAAI,QAAQ,GAA0B,IAAI,CAAA;IAC1C,IAAI,QAAQ,GAAG,EAAE,CAAA;IACjB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;YACjE,IAAI,CAAC,QAAQ;gBAAE,OAAM;YACrB,IAAI,QAAQ;gBAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;YACpC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAA;YAC9B,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;gBACzB,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACpB,CAAC,EAAE,EAAE,CAAC,CAAA;QACR,CAAC,CAAC,CAAA;QACF,sEAAsE;QACtE,qDAAqD;QACrD,CAAC,CAAC,KAAK,EAAE,EAAE,CAAA;QACX,aAAa,GAAG,CAAC,CAAA;IACnB,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,SAAS,CAAC,uBAAuB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;IAC/C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,aAAa,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,aAAa,GAAG,IAAI,CAAA;IACtB,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"shortcuts.d.ts","sourceRoot":"","sources":["../../src/runtime/shortcuts.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAW/D;AAED,wBAAgB,aAAa,IAAI,IAAI,CAIpC"}
1
+ {"version":3,"file":"shortcuts.d.ts","sourceRoot":"","sources":["../../src/runtime/shortcuts.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAI/D;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC"}
@@ -1,29 +1,16 @@
1
- // Terminal keyboard shortcuts (raw mode stdin).
1
+ // Quit handler. We previously had `o`/`r`/`q` keypress shortcuts via stdin
2
+ // raw mode, but attaching any listener to stdin caused the OS close button
3
+ // to hang (stdin polling conflicted with the Cocoa main loop).
2
4
  //
3
- // o open the window
4
- // r restart (close + open)
5
- // q quit
6
- // Ctrl+C quit
5
+ // Now: just listen for SIGINT/SIGTERM (Ctrl+C, kill signal). The OS close
6
+ // button + Ctrl+C cover quit. Future work: bring back o/r via the native
7
+ // menu API (webview's Menu/Tray surface), which doesn't touch stdin.
7
8
  export function setupShortcuts(handlers) {
8
- if (!process.stdin.isTTY)
9
- return;
10
- process.stdin.setRawMode(true);
11
- process.stdin.resume();
12
- process.stdin.setEncoding('utf8');
13
- process.stdin.on('data', (key) => {
14
- const k = key.toString();
15
- if (k === 'o' || k === 'O')
16
- handlers.onOpen();
17
- else if (k === 'r' || k === 'R')
18
- handlers.onRestart();
19
- else if (k === 'q' || k === 'Q' || k === '\x03' /* Ctrl+C */)
20
- handlers.onQuit();
21
- });
9
+ const quit = () => handlers.onQuit();
10
+ process.on('SIGINT', quit);
11
+ process.on('SIGTERM', quit);
22
12
  }
23
13
  export function teardownStdin() {
24
- try {
25
- process.stdin.setRawMode(false);
26
- }
27
- catch { }
14
+ // no-op (we never touched stdin)
28
15
  }
29
16
  //# sourceMappingURL=shortcuts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shortcuts.js","sourceRoot":"","sources":["../../src/runtime/shortcuts.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,wBAAwB;AACxB,+BAA+B;AAC/B,aAAa;AACb,kBAAkB;AAQlB,MAAM,UAAU,cAAc,CAAC,QAA0B;IACvD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAM;IAChC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IAC9B,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;IACtB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QAC/B,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAA;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;aACxC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,QAAQ,CAAC,SAAS,EAAE,CAAA;aAChD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC,YAAY;YAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;IACjF,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"shortcuts.js","sourceRoot":"","sources":["../../src/runtime/shortcuts.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2EAA2E;AAC3E,+DAA+D;AAC/D,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,qEAAqE;AAQrE,MAAM,UAAU,cAAc,CAAC,QAA0B;IACvD,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAA;IACpC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAC1B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,iCAAiC;AACnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../src/runtime/window.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAe,MAAM,oBAAoB,CAAA;AAI7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAU/C,eAAO,MAAM,GAAG,aAAqD,CAAA;AA+BrE,wBAAgB,SAAS,IAAI,QAAQ,CAAC,YAAY,CAAC,CAElD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBhD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAOlC;AAED,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASrE;AAED,wBAAgB,MAAM,IAAI,IAAI,CAE7B;AAED,wBAAgB,OAAO,IAAI,IAAI,CAI9B"}
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../src/runtime/window.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAIhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAe/C,eAAO,MAAM,GAAG,aAAoB,CAAA;AAmDpC,wBAAgB,SAAS,IAAI,QAAQ,CAAC,YAAY,CAAC,CAElD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBhD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAKlC;AAED,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASrE;AAED,wBAAgB,MAAM,IAAI,IAAI,CAE7B;AAED,wBAAgB,OAAO,IAAI,IAAI,CAI9B"}
@@ -1,11 +1,8 @@
1
1
  // Owns the Application + BrowserWindow lifecycle.
2
- //
3
- // The EventLoop is created exactly once (winit/tao limitation). ControlFlow.Wait
4
- // keeps the loop alive even when no windows are open, so the user can press
5
- // `o` in the terminal to re-open the window.
6
- import { Application, ControlFlow } from '@webviewjs/webview';
7
- import { printClosed, printError, printHint, printReloaded } from "../cli/log.js";
2
+ import { Application } from '@webviewjs/webview';
3
+ import { printBye, printClosed, printError, printHint, printReloaded } from "../cli/log.js";
8
4
  import { DEFAULT_WIN_SIZE, DEFAULT_WIN_TITLE, projectRoot } from "../env.js";
5
+ import { teardownHmr } from "./hmr.js";
9
6
  import { nativeBridge } from "./native.js";
10
7
  import { renderApp } from "./render.js";
11
8
  const config = {
@@ -13,24 +10,49 @@ const config = {
13
10
  width: DEFAULT_WIN_SIZE.width,
14
11
  height: DEFAULT_WIN_SIZE.height,
15
12
  };
16
- export const app = new Application({ controlFlow: ControlFlow.Wait });
13
+ // Default event-loop mode (pump_events at ~60 FPS). ControlFlow.Wait used to
14
+ // be set here to allow `o` re-open after close, but it caused the close
15
+ // button to hang waiting for the next pump tick, which macOS interpreted
16
+ // as "not responding". Plain run-loop is responsive and just as cheap.
17
+ export const app = new Application();
17
18
  let win = null;
18
19
  let webview = null;
20
+ // winit/wry distinguishes two close events:
21
+ // - window-close-requested → one window's red button
22
+ // - application-close-requested → last window closed → app should exit
23
+ // We MUST handle the latter and call app.exit(), otherwise the OS sees
24
+ // the process as alive but unresponsive (no pending GUI work, no exit).
19
25
  app.onEvent((event) => {
20
26
  const kind = event && (event.kind || event.event);
21
27
  if (kind === 'window-close-requested') {
22
- // Dispose so the OS close completes — without this the close button hangs.
23
- if (win) {
24
- try {
25
- win.dispose();
26
- }
27
- catch { }
28
- }
29
- win = null;
30
28
  webview = null;
29
+ win = null;
31
30
  printClosed();
31
+ return;
32
+ }
33
+ if (kind === 'application-close-requested') {
34
+ teardownHmr();
35
+ printBye();
36
+ try {
37
+ app.exit();
38
+ }
39
+ catch { }
40
+ process.exit(0);
32
41
  }
33
42
  });
43
+ // Manual close path (the `r` shortcut for restart). We reopen immediately
44
+ // after, so explicit dispose is desirable.
45
+ function disposeSafely(target) {
46
+ if (!target)
47
+ return;
48
+ const sym = target[Symbol.dispose];
49
+ if (typeof sym === 'function') {
50
+ try {
51
+ sym.call(target);
52
+ }
53
+ catch { }
54
+ }
55
+ }
34
56
  function applyMetadata(metadata) {
35
57
  if (!metadata)
36
58
  return;
@@ -68,14 +90,10 @@ export async function openWindow() {
68
90
  }
69
91
  }
70
92
  export function closeWindow() {
71
- if (!win)
72
- return;
73
- try {
74
- win.dispose();
75
- }
76
- catch { }
77
- win = null;
93
+ disposeSafely(webview);
94
+ disposeSafely(win);
78
95
  webview = null;
96
+ win = null;
79
97
  }
80
98
  export async function reloadWindow(triggerFile) {
81
99
  if (!webview)
@@ -1 +1 @@
1
- {"version":3,"file":"window.js","sourceRoot":"","sources":["../../src/runtime/window.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,iFAAiF;AACjF,4EAA4E;AAC5E,6CAA6C;AAE7C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AACjF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAc,CAAA;AAExC,MAAM,MAAM,GAAiB;IAC3B,KAAK,EAAE,iBAAiB;IACxB,KAAK,EAAE,gBAAgB,CAAC,KAAK;IAC7B,MAAM,EAAE,gBAAgB,CAAC,MAAM;CAChC,CAAA;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,CAAA;AAKrE,IAAI,GAAG,GAAyB,IAAI,CAAA;AACpC,IAAI,OAAO,GAAmB,IAAI,CAAA;AAElC,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;IACpB,MAAM,IAAI,GAAG,KAAK,IAAI,CAAE,KAAa,CAAC,IAAI,IAAK,KAAa,CAAC,KAAK,CAAC,CAAA;IACnE,IAAI,IAAI,KAAK,wBAAwB,EAAE,CAAC;QACtC,2EAA2E;QAC3E,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC;gBACH,GAAG,CAAC,OAAO,EAAE,CAAA;YACf,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;QACD,GAAG,GAAG,IAAI,CAAA;QACV,OAAO,GAAG,IAAI,CAAA;QACd,WAAW,EAAE,CAAA;IACf,CAAC;AACH,CAAC,CAAC,CAAA;AAEF,SAAS,aAAa,CAAC,QAAmB;IACxC,IAAI,CAAC,QAAQ;QAAE,OAAM;IACrB,IAAI,QAAQ,CAAC,MAAM,EAAE,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAA;SAC3D,IAAI,QAAQ,CAAC,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAA;IACtD,IAAI,QAAQ,CAAC,MAAM,EAAE,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAA;IAChE,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAA;AACrE,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,GAAG,EAAE,CAAC;QACR,SAAS,CAAC,wBAAwB,CAAC,CAAA;QACnC,OAAM;IACR,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;IAC5C,aAAa,CAAC,QAAQ,CAAC,CAAA;IACvB,GAAG,GAAG,GAAG,CAAC,mBAAmB,CAAC;QAC5B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAA;IACF,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IACrC,+DAA+D;IAC/D,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,UAAU,CAAC,gCAAgC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;IACzD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,GAAG;QAAE,OAAM;IAChB,IAAI,CAAC;QACH,GAAG,CAAC,OAAO,EAAE,CAAA;IACf,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,GAAG,GAAG,IAAI,CAAA;IACV,OAAO,GAAG,IAAI,CAAA;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IACpD,IAAI,CAAC,OAAO;QAAE,OAAM;IACpB,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;QAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACtB,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,CAAA;IAC3D,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,UAAU,CAAC,kBAAkB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;IAC3C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,GAAG,CAAC,GAAG,EAAE,CAAA;AACX,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,IAAI,CAAC;QACH,GAAG,CAAC,IAAI,EAAE,CAAA;IACZ,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"window.js","sourceRoot":"","sources":["../../src/runtime/window.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "murasaki",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "The desktop framework for Next.js developers. Node-powered. WebView-thin. No Rust. No Chromium.",
5
5
  "keywords": [
6
6
  "desktop",