@bobfrankston/mailx 1.0.1 → 1.0.3
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/bin/mailx.js +39 -26
- package/package.json +15 -3
- package/packages/mailx-server/index.js +13 -2
- package/packages/mailx-server/package.json +1 -1
- package/launcher/Cargo.lock +0 -3167
- package/launcher/Cargo.toml +0 -13
- package/launcher/build.cmd +0 -4
- package/launcher/build.rs +0 -8
- package/launcher/mailx.ico +0 -0
- package/launcher/release.cmd +0 -4
- package/launcher/src/main.rs +0 -371
- package/mailx.cmd +0 -2
- package/mailx.db +0 -0
- package/mailx.db-shm +0 -0
- package/mailx.db-wal +0 -0
package/bin/mailx.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* mailx
|
|
4
|
-
*
|
|
3
|
+
* mailx — email client launcher
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* mailx Start unified (in-process server + open browser)
|
|
7
|
+
* mailx --server Start as a standalone server only (no browser)
|
|
8
|
+
* mailx --no-browser Start server in-process, don't open browser
|
|
9
|
+
* mailx --external Bind to all interfaces (default: localhost only)
|
|
5
10
|
*/
|
|
6
11
|
|
|
7
|
-
import { spawn } from "node:child_process";
|
|
8
12
|
import { fileURLToPath } from "node:url";
|
|
9
13
|
import path from "node:path";
|
|
10
14
|
import net from "node:net";
|
|
11
15
|
|
|
12
16
|
const PORT = 9333;
|
|
13
17
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
-
const
|
|
18
|
+
const args = process.argv.slice(2);
|
|
15
19
|
|
|
16
20
|
function isPortInUse(port) {
|
|
17
21
|
return new Promise((resolve) => {
|
|
@@ -22,36 +26,45 @@ function isPortInUse(port) {
|
|
|
22
26
|
});
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
function openBrowser(url) {
|
|
30
|
+
import("node:child_process").then(({ exec }) => {
|
|
31
|
+
if (process.platform === "win32") exec(`start "" "${url}"`);
|
|
32
|
+
else if (process.platform === "darwin") exec(`open "${url}"`);
|
|
33
|
+
else exec(`xdg-open "${url}"`);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
25
37
|
async function main() {
|
|
26
|
-
const
|
|
27
|
-
const noBrowser = args.includes("--no-browser");
|
|
28
|
-
const inUse = await isPortInUse(PORT);
|
|
38
|
+
const serverOnly = args.includes("--server");
|
|
39
|
+
const noBrowser = args.includes("--no-browser") || serverOnly;
|
|
29
40
|
|
|
41
|
+
const inUse = await isPortInUse(PORT);
|
|
30
42
|
if (inUse) {
|
|
31
43
|
console.log(`mailx server already running on port ${PORT}`);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const child = spawn(process.execPath, serverArgs, {
|
|
36
|
-
stdio: "inherit",
|
|
37
|
-
detached: false,
|
|
38
|
-
});
|
|
39
|
-
child.unref();
|
|
40
|
-
|
|
41
|
-
// Wait for server to be ready
|
|
42
|
-
for (let i = 0; i < 60; i++) {
|
|
43
|
-
await new Promise(r => setTimeout(r, 500));
|
|
44
|
-
if (await isPortInUse(PORT)) break;
|
|
44
|
+
if (!noBrowser) {
|
|
45
|
+
openBrowser(`http://localhost:${PORT}`);
|
|
46
|
+
console.log(`Opened http://localhost:${PORT}`);
|
|
45
47
|
}
|
|
48
|
+
return;
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
// Start server in-process (unified mode)
|
|
52
|
+
console.log(`Starting mailx on port ${PORT}...`);
|
|
53
|
+
|
|
54
|
+
// Pass --external to server if requested
|
|
55
|
+
if (args.includes("--external")) process.argv.push("--external");
|
|
56
|
+
|
|
57
|
+
// Import and start the server directly — no subprocess
|
|
58
|
+
await import(path.join(__dirname, "..", "packages", "mailx-server", "index.js"));
|
|
59
|
+
|
|
48
60
|
if (!noBrowser) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
// Wait a moment for server to be ready
|
|
62
|
+
for (let i = 0; i < 30; i++) {
|
|
63
|
+
await new Promise(r => setTimeout(r, 200));
|
|
64
|
+
if (await isPortInUse(PORT)) break;
|
|
65
|
+
}
|
|
66
|
+
openBrowser(`http://localhost:${PORT}`);
|
|
67
|
+
console.log(`Opened http://localhost:${PORT}`);
|
|
55
68
|
}
|
|
56
69
|
}
|
|
57
70
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Local-first email client with IMAP sync and standalone native app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/mailx.js",
|
|
@@ -22,8 +22,14 @@
|
|
|
22
22
|
"@bobfrankston/iflow": "^1.0.2",
|
|
23
23
|
"@bobfrankston/miscinfo": "^1.0.5",
|
|
24
24
|
"@bobfrankston/oauthsupport": "^1.0.10",
|
|
25
|
+
"@bobfrankston/certsupport": "^1.0.35",
|
|
26
|
+
"better-sqlite3": "^11.0.0",
|
|
27
|
+
"express": "^4.21.0",
|
|
28
|
+
"jsonc-parser": "^3.3.1",
|
|
25
29
|
"mailparser": "^3.7.2",
|
|
26
|
-
"
|
|
30
|
+
"nodemailer": "^7.0.0",
|
|
31
|
+
"quill": "^2.0.3",
|
|
32
|
+
"ws": "^8.18.0"
|
|
27
33
|
},
|
|
28
34
|
"devDependencies": {
|
|
29
35
|
"@types/mailparser": "^3.4.6"
|
|
@@ -45,7 +51,13 @@
|
|
|
45
51
|
"@bobfrankston/iflow": "file:../MailApps/iflow",
|
|
46
52
|
"@bobfrankston/miscinfo": "file:../../projects/npm/miscinfo",
|
|
47
53
|
"@bobfrankston/oauthsupport": "file:../../projects/oauth/oauthsupport",
|
|
54
|
+
"@bobfrankston/certsupport": "file:../../projects/nodejs/certsupport",
|
|
55
|
+
"better-sqlite3": "^11.0.0",
|
|
56
|
+
"express": "^4.21.0",
|
|
57
|
+
"jsonc-parser": "^3.3.1",
|
|
48
58
|
"mailparser": "^3.7.2",
|
|
49
|
-
"
|
|
59
|
+
"nodemailer": "^7.0.0",
|
|
60
|
+
"quill": "^2.0.3",
|
|
61
|
+
"ws": "^8.18.0"
|
|
50
62
|
}
|
|
51
63
|
}
|
|
@@ -14,8 +14,19 @@ import { ports } from "@bobfrankston/miscinfo";
|
|
|
14
14
|
import { InitServerAsync, InitServerOptions } from "@bobfrankston/certsupport";
|
|
15
15
|
const PORT = ports.mailx;
|
|
16
16
|
// ── File logging ──
|
|
17
|
-
const logDir = path.join(
|
|
18
|
-
|
|
17
|
+
const logDir = path.join(process.env.USERPROFILE || process.env.HOME || ".", ".mailx");
|
|
18
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
19
|
+
// Rotate: delete logs older than 7 days
|
|
20
|
+
try {
|
|
21
|
+
for (const f of fs.readdirSync(logDir).filter(f => f.startsWith("mailx-") && f.endsWith(".log"))) {
|
|
22
|
+
const stat = fs.statSync(path.join(logDir, f));
|
|
23
|
+
if (Date.now() - stat.mtimeMs > 7 * 86400000)
|
|
24
|
+
fs.unlinkSync(path.join(logDir, f));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch { /* ignore cleanup errors */ }
|
|
28
|
+
const logDate = new Date().toISOString().slice(0, 10);
|
|
29
|
+
const logPath = path.join(logDir, `mailx-${logDate}.log`);
|
|
19
30
|
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
20
31
|
const origLog = console.log;
|
|
21
32
|
const origErr = console.error;
|