@bobfrankston/msger 0.1.360 → 0.1.361

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/msger",
3
- "version": "0.1.360",
3
+ "version": "0.1.361",
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.js CHANGED
@@ -362,42 +362,40 @@ function resolveBinaryPath() {
362
362
  }
363
363
  function createMessageBoxHandle(options) {
364
364
  const binaryPath = resolveBinaryPath();
365
- // Declare variables that will be used outside the Promise
365
+ // Validate the binary up front and synchronously. Doing this inside the
366
+ // Promise executor used to leave `child` undefined when the binary was
367
+ // missing, then `new MessageBoxHandle(child, ...)` blew up on `child.pid`
368
+ // with a cryptic "cannot read properties of undefined" — masking the real
369
+ // "binary not found" message. Throw directly here so callers see the
370
+ // actual cause.
371
+ if (!fs.existsSync(binaryPath)) {
372
+ throw new Error(`msger native binary not found at: ${binaryPath}\n` +
373
+ `Platform: ${platform()} ${process.arch}. ` +
374
+ `If you just installed @bobfrankston/msger, the published package may be missing the binary for this platform.`);
375
+ }
376
+ if (platform() !== 'win32') {
377
+ try {
378
+ fs.accessSync(binaryPath, fs.constants.X_OK);
379
+ }
380
+ catch {
381
+ throw new Error(`msger native binary is not executable: ${binaryPath}\n` +
382
+ `Please run: chmod +x "${binaryPath}"`);
383
+ }
384
+ }
366
385
  const childEnv = { ...process.env };
367
386
  if ('NODE_OPTIONS' in childEnv) {
368
387
  delete childEnv.NODE_OPTIONS;
369
388
  }
370
- let child;
389
+ // Spawn before constructing the Promise so `child` is guaranteed defined
390
+ // by the time we hand it to MessageBoxHandle.
391
+ const child = spawn(binaryPath, [], {
392
+ stdio: options.detach ? ['pipe', 'ignore', 'ignore'] : ['pipe', 'pipe', 'pipe'],
393
+ detached: options.detach || false,
394
+ env: childEnv
395
+ });
371
396
  let stdout = '';
372
397
  let stderr = '';
373
398
  const resultPromise = new Promise((resolve, reject) => {
374
- // Check if binary exists
375
- if (!fs.existsSync(binaryPath)) {
376
- reject(new Error(`Binary not found: ${binaryPath}`));
377
- return;
378
- }
379
- // On Unix systems, check if binary is executable
380
- if (platform() !== 'win32') {
381
- try {
382
- fs.accessSync(binaryPath, fs.constants.X_OK);
383
- }
384
- catch (error) {
385
- reject(new Error(`Binary is not executable: ${binaryPath}\n` +
386
- `Please run: sudo chmod +x ${binaryPath}`));
387
- return;
388
- }
389
- }
390
- // Spawn the Rust binary
391
- // Spawn child with a sanitized environment. Electron will print
392
- // warnings if NODE_OPTIONS is present in the environment of a
393
- // packaged app. Remove NODE_OPTIONS to avoid that warning.
394
- // When detached, use 'ignore' for stdout/stderr so parent can exit
395
- // We only need stdin to send the options, not to receive results
396
- child = spawn(binaryPath, [], {
397
- stdio: options.detach ? ['pipe', 'ignore', 'ignore'] : ['pipe', 'pipe', 'pipe'],
398
- detached: options.detach || false,
399
- env: childEnv
400
- });
401
399
  // If detached, unref the child so parent can exit
402
400
  if (options.detach) {
403
401
  child.unref();