@bobfrankston/mailx 1.0.24 → 1.0.26

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.
Files changed (2) hide show
  1. package/bin/mailx.js +59 -9
  2. package/package.json +1 -1
package/bin/mailx.js CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * mailx email client
3
+ * mailx -- email client
4
4
  *
5
5
  * Usage:
6
- * mailx Launch native app (IPC, no server)
6
+ * mailx Launch native app or fallback to browser
7
7
  * mailx --server Start Express server + open browser
8
8
  * mailx --no-browser Server mode, don't open browser
9
9
  * mailx --external Bind to all interfaces (server mode only)
10
+ * mailx --verbose Show detailed startup info
11
+ * mailx -v / --version Show version and exit
10
12
  */
11
13
 
12
14
  import fs from "node:fs";
@@ -17,6 +19,43 @@ const PORT = 9333;
17
19
  const args = process.argv.slice(2);
18
20
  const serverMode = args.includes("--server");
19
21
  const noBrowser = args.includes("--no-browser");
22
+ const verbose = args.includes("--verbose");
23
+
24
+ function log(...msg) { if (verbose) console.log("[mailx]", ...msg); }
25
+
26
+ // Kill any running mailx server
27
+ if (args.includes("--kill") || args.includes("-kill")) {
28
+ log("Killing mailx processes...");
29
+ const { execSync } = await import("node:child_process");
30
+ // Kill by port
31
+ try {
32
+ if (process.platform === "win32") {
33
+ const out = execSync(`netstat -ano | findstr :${PORT} | findstr LISTENING`, { encoding: "utf-8" }).trim();
34
+ const pids = [...new Set(out.split("\n").map(l => l.trim().split(/\s+/).pop()).filter(Boolean))];
35
+ for (const pid of pids) {
36
+ try { execSync(`taskkill /F /PID ${pid}`, { stdio: "pipe" }); console.log(`Killed PID ${pid}`); } catch { /* */ }
37
+ }
38
+ } else {
39
+ try { execSync(`fuser -k ${PORT}/tcp`, { stdio: "pipe" }); console.log(`Killed process on port ${PORT}`); } catch { /* */ }
40
+ }
41
+ } catch { console.log(`No process found on port ${PORT}`); }
42
+ // Remove lock file
43
+ const lockPath = path.join(process.env.USERPROFILE || process.env.HOME || ".", ".mailx", "mailx-app.lock");
44
+ try { fs.unlinkSync(lockPath); log("Removed lock file"); } catch { /* */ }
45
+ process.exit(0);
46
+ }
47
+
48
+ // Version
49
+ if (args.includes("-v") || args.includes("--version") || args.includes("-version")) {
50
+ const pkgPath = path.join(import.meta.dirname, "..", "package.json");
51
+ try {
52
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
53
+ console.log(`mailx v${pkg.version}`);
54
+ } catch {
55
+ console.log("mailx (version unknown)");
56
+ }
57
+ process.exit(0);
58
+ }
20
59
 
21
60
  function isPortInUse(port) {
22
61
  return new Promise((resolve) => {
@@ -35,16 +74,21 @@ function openBrowser(url) {
35
74
  }
36
75
 
37
76
  async function main() {
77
+ log(`Platform: ${process.platform} ${process.arch}`);
78
+ log(`Node: ${process.version}`);
79
+ log(`Mode: ${serverMode ? "server" : "auto-detect"}`);
80
+
38
81
  if (serverMode) {
39
82
  // Server mode — Express + WebSocket, open browser
40
83
  const inUse = await isPortInUse(PORT);
41
84
  if (inUse) {
42
- console.log("mailx server already running");
43
- if (!noBrowser) openBrowser(`http://localhost:${PORT}`);
85
+ console.log(`mailx server already running on port ${PORT}`);
86
+ if (!noBrowser) openBrowser(`http://127.0.0.1:${PORT}`);
44
87
  return;
45
88
  }
46
89
 
47
90
  console.log("Starting mailx server...");
91
+ log(`Loading server from: ${path.join(import.meta.dirname, "..", "packages", "mailx-server", "index.js")}`);
48
92
  if (args.includes("--external")) process.argv.push("--external");
49
93
  await import("../packages/mailx-server/index.js");
50
94
 
@@ -53,12 +97,14 @@ async function main() {
53
97
  await new Promise(r => setTimeout(r, 200));
54
98
  if (await isPortInUse(PORT)) break;
55
99
  }
56
- openBrowser(`http://localhost:${PORT}`);
100
+ openBrowser(`http://127.0.0.1:${PORT}`);
57
101
  console.log("mailx opened (browser)");
58
102
  }
103
+
104
+ // Keep process alive — server is running
105
+ await new Promise(() => {});
59
106
  } else {
60
- // Default: launch native WebView app with IPC
61
- // Platform-specific binary naming (matches msger pattern)
107
+ // Default: launch native WebView app
62
108
  let binaryName;
63
109
  if (process.platform === "win32") binaryName = "mailx-app.exe";
64
110
  else if (process.platform === "darwin") binaryName = process.arch === "arm64" ? "mailx-app-arm64" : "mailx-app";
@@ -69,17 +115,21 @@ async function main() {
69
115
  path.join(import.meta.dirname, "..", "launcher", "target", "release", binaryName),
70
116
  ];
71
117
 
118
+ log(`Looking for native launcher: ${binaryName}`);
119
+ for (const p of launcherPaths) log(` ${fs.existsSync(p) ? "FOUND" : "not found"}: ${p}`);
120
+
72
121
  let launcherPath = launcherPaths.find(p => fs.existsSync(p));
73
122
 
74
123
  if (launcherPath) {
75
124
  console.log("Starting mailx...");
125
+ log(`Launching: ${launcherPath}`);
76
126
  const { spawn } = await import("node:child_process");
77
127
  const child = spawn(launcherPath, args, { detached: true, stdio: "ignore" });
78
128
  child.unref();
79
129
  console.log("mailx launched");
80
130
  } else {
81
- // No native launcher fall back to server mode + browser
82
- console.log("Native launcher not found, falling back to server mode");
131
+ console.log("Native launcher not found, starting in browser mode...");
132
+ log("Falling back to --server mode");
83
133
  process.argv.push("--server");
84
134
  await main(); // recurse with --server
85
135
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",