@bobfrankston/msger 0.1.196 → 0.1.197

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/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { showMessageBox, MessageBoxOptions, MessageBoxResult } from "./shower.js";
1
+ export { showMessageBox, showService, ServiceHandle, MessageBoxOptions, MessageBoxResult } from "./shower.js";
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Export showMessageBox and types for use as a library
2
- export { showMessageBox } from "./shower.js";
2
+ export { showMessageBox, showService, ServiceHandle } from "./shower.js";
3
3
  // If run directly (e.g., `node .` or `node index.js`), run the CLI
4
4
  // @ts-ignore - import.meta.main is available in Node.js 20+
5
5
  if (import.meta.main) {
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/msger",
3
- "version": "0.1.196",
3
+ "version": "0.1.197",
4
4
  "description": "Fast, lightweight, cross-platform message box - Rust-powered alternative to msgview",
5
5
  "type": "module",
6
6
  "main": "./index.js",
package/shower.d.ts CHANGED
@@ -41,6 +41,8 @@ export interface MessageBoxOptions {
41
41
  debug?: boolean; /** Return debug information (HTML, size) in result (default: false) */
42
42
  showVersion?: boolean; /** Show version in window title (default: false) */
43
43
  appUserModelId?: string; /** Windows AppUserModelID for taskbar pinning (internal use) */
44
+ initScript?: string; /** Custom JS injected into WebView alongside msger-api.js */
45
+ service?: boolean; /** Service mode: bidirectional IPC with parent. Stdin/stdout stay open. */
44
46
  }
45
47
  export interface MessageBoxResult {
46
48
  button: string;
@@ -68,3 +70,23 @@ export declare function showMessageBoxEx(options: MessageBoxOptions): MessageBox
68
70
  * @returns Promise that resolves with user's response
69
71
  */
70
72
  export declare function showMessageBox(options: MessageBoxOptions): Promise<MessageBoxResult>;
73
+ export type ServiceRequestHandler = (request: any) => void;
74
+ /** Handle for a service-mode msger instance. Bidirectional IPC with the WebView. */
75
+ export declare class ServiceHandle {
76
+ private child;
77
+ private _closed;
78
+ private _onRequest;
79
+ readonly closed: Promise<void>;
80
+ constructor(child: ChildProcess);
81
+ /** Register handler for requests from the WebView (_action messages) */
82
+ onRequest(handler: ServiceRequestHandler): void;
83
+ /** Send a response or event to the WebView (written to child's stdin) */
84
+ send(msg: any): void;
85
+ /** Close the window */
86
+ close(): void;
87
+ }
88
+ /**
89
+ * Open msger in service mode — bidirectional IPC, no HTTP.
90
+ * Parent process handles requests via onRequest, sends responses via send().
91
+ */
92
+ export declare function showService(options: Omit<MessageBoxOptions, "service" | "detach">): ServiceHandle;
package/shower.js CHANGED
@@ -262,3 +262,89 @@ export function showMessageBoxEx(options) {
262
262
  export async function showMessageBox(options) {
263
263
  return showMessageBoxEx(options).result;
264
264
  }
265
+ /** Handle for a service-mode msger instance. Bidirectional IPC with the WebView. */
266
+ export class ServiceHandle {
267
+ child;
268
+ _closed = false;
269
+ _onRequest = null;
270
+ closed;
271
+ constructor(child) {
272
+ this.child = child;
273
+ // Parse stdout as newline-delimited JSON (requests from WebView)
274
+ let buffer = "";
275
+ child.stdout?.on("data", (data) => {
276
+ buffer += data.toString();
277
+ let newline;
278
+ while ((newline = buffer.indexOf("\n")) >= 0) {
279
+ const line = buffer.slice(0, newline).trim();
280
+ buffer = buffer.slice(newline + 1);
281
+ if (!line)
282
+ continue;
283
+ try {
284
+ const msg = JSON.parse(line);
285
+ if (this._onRequest)
286
+ this._onRequest(msg);
287
+ }
288
+ catch { /* ignore malformed lines */ }
289
+ }
290
+ });
291
+ this.closed = new Promise((resolve) => {
292
+ child.on("close", () => { this._closed = true; resolve(); });
293
+ });
294
+ }
295
+ /** Register handler for requests from the WebView (_action messages) */
296
+ onRequest(handler) {
297
+ this._onRequest = handler;
298
+ }
299
+ /** Send a response or event to the WebView (written to child's stdin) */
300
+ send(msg) {
301
+ if (this._closed)
302
+ return;
303
+ this.child.stdin?.write(JSON.stringify(msg) + "\n");
304
+ }
305
+ /** Close the window */
306
+ close() {
307
+ if (this._closed)
308
+ return;
309
+ this._closed = true;
310
+ this.child.kill();
311
+ }
312
+ }
313
+ /**
314
+ * Open msger in service mode — bidirectional IPC, no HTTP.
315
+ * Parent process handles requests via onRequest, sends responses via send().
316
+ */
317
+ export function showService(options) {
318
+ const serviceOptions = { ...options, service: true, detach: false };
319
+ const isWindows = platform() === "win32";
320
+ const arch = process.arch;
321
+ let binaryName;
322
+ if (isWindows)
323
+ binaryName = "msgernative.exe";
324
+ else if (arch === "arm64")
325
+ binaryName = "msgernative-linux-aarch64";
326
+ else
327
+ binaryName = "msgernative";
328
+ const binaryPath = path.join(import.meta.dirname, "msger-native", "bin", binaryName);
329
+ const childEnv = { ...process.env };
330
+ if ("NODE_OPTIONS" in childEnv)
331
+ delete childEnv.NODE_OPTIONS;
332
+ const child = spawn(binaryPath, [], {
333
+ stdio: ["pipe", "pipe", "pipe"],
334
+ env: childEnv,
335
+ });
336
+ child.stderr?.on("data", (data) => {
337
+ // Forward Rust stderr to parent stderr (debug messages)
338
+ process.stderr.write(data);
339
+ });
340
+ child.stdin?.on("error", () => { });
341
+ // Send options as first line of stdin (Rust reads one line for options, then keeps reading)
342
+ const rustOptions = { ...serviceOptions };
343
+ if (rustOptions.size) {
344
+ rustOptions.width = rustOptions.size.width;
345
+ rustOptions.height = rustOptions.size.height;
346
+ delete rustOptions.size;
347
+ }
348
+ child.stdin?.write(JSON.stringify(rustOptions) + "\n");
349
+ return new ServiceHandle(child);
350
+ }