@bobfrankston/mailx 1.0.139 → 1.0.141
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 +24 -39
- package/package.json +4 -4
- package/packages/mailx-server/index.js +3 -2
- package/launcher/bin/mailx-app-linux +0 -0
- package/launcher/bin/mailx-app.exe +0 -0
- package/launcher/builder/build-config.json +0 -11
- package/launcher/builder/postinstall.js +0 -73
- package/launcher/mailx.ico +0 -0
package/bin/mailx.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* mailx -- email client
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
|
-
* mailx Start server + open in msger
|
|
7
|
-
* mailx --server Start server + open
|
|
6
|
+
* mailx Start server + open in msger
|
|
7
|
+
* mailx --server Start server + open msger (same as default)
|
|
8
8
|
* mailx --no-browser Start server only (headless)
|
|
9
9
|
* mailx --external Bind to all interfaces
|
|
10
10
|
* mailx --verbose Show detailed startup info
|
|
@@ -18,6 +18,7 @@ import fs from "node:fs";
|
|
|
18
18
|
import path from "node:path";
|
|
19
19
|
import net from "node:net";
|
|
20
20
|
import { ports } from "@bobfrankston/miscinfo";
|
|
21
|
+
import { showMessageBox } from "@bobfrankston/msger";
|
|
21
22
|
const PORT = ports.mailx;
|
|
22
23
|
const args = process.argv.slice(2);
|
|
23
24
|
// Normalize: accept both -flag and --flag
|
|
@@ -30,7 +31,7 @@ const addMode = hasFlag("add");
|
|
|
30
31
|
const testMode = hasFlag("test");
|
|
31
32
|
const rebuildMode = hasFlag("rebuild");
|
|
32
33
|
// Validate arguments
|
|
33
|
-
const knownFlags = ["server", "no-browser", "verbose", "external", "kill", "v", "version", "setup", "add", "test", "rebuild", "native-imap"];
|
|
34
|
+
const knownFlags = ["server", "no-browser", "verbose", "external", "kill", "v", "version", "setup", "add", "test", "rebuild", "native-imap", "log"];
|
|
34
35
|
for (const arg of args) {
|
|
35
36
|
const flag = arg.replace(/^--?/, "");
|
|
36
37
|
if (arg.startsWith("-") && !knownFlags.includes(flag)) {
|
|
@@ -147,7 +148,7 @@ if (hasFlag("v") || hasFlag("version")) {
|
|
|
147
148
|
};
|
|
148
149
|
try {
|
|
149
150
|
const pkg = JSON.parse(fs.readFileSync(`${root}/package.json`, "utf-8"));
|
|
150
|
-
console.log(
|
|
151
|
+
console.log(`\x1b[1;97;44m mailx v${pkg.version} \x1b[0m`);
|
|
151
152
|
}
|
|
152
153
|
catch {
|
|
153
154
|
console.log("mailx (version unknown)");
|
|
@@ -169,26 +170,9 @@ function isPortInUse(port) {
|
|
|
169
170
|
socket.once("error", () => resolve(false));
|
|
170
171
|
});
|
|
171
172
|
}
|
|
172
|
-
|
|
173
|
-
import("node:child_process").then(({ exec }) => {
|
|
174
|
-
if (process.platform === "win32")
|
|
175
|
-
exec(`start "" "${url}"`);
|
|
176
|
-
else if (process.platform === "darwin")
|
|
177
|
-
exec(`open "${url}"`);
|
|
178
|
-
else
|
|
179
|
-
exec(`xdg-open "${url}"`);
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
/** Launch msger pointing at the server URL; fall back to browser if msger not found */
|
|
173
|
+
/** Launch msger pointing at the server URL */
|
|
183
174
|
function launchMsger(url) {
|
|
184
|
-
|
|
185
|
-
const child = spawn("msger", ["-url", url], { detached: true, stdio: "ignore" });
|
|
186
|
-
child.on("error", () => {
|
|
187
|
-
log("msger not found — opening in browser");
|
|
188
|
-
openBrowser(url);
|
|
189
|
-
});
|
|
190
|
-
child.unref();
|
|
191
|
-
});
|
|
175
|
+
showMessageBox({ url, detach: true, size: { width: 1400, height: 900 } });
|
|
192
176
|
}
|
|
193
177
|
async function prompt(question) {
|
|
194
178
|
const readline = await import("readline");
|
|
@@ -507,19 +491,27 @@ async function main() {
|
|
|
507
491
|
// Check if server is already running
|
|
508
492
|
const inUse = await isPortInUse(PORT);
|
|
509
493
|
if (inUse) {
|
|
510
|
-
console.log(`mailx server already running on port ${PORT}`);
|
|
511
494
|
const url = `http://127.0.0.1:${PORT}`;
|
|
512
|
-
if (!noBrowser)
|
|
513
|
-
|
|
514
|
-
openBrowser(url);
|
|
515
|
-
else
|
|
516
|
-
launchMsger(url);
|
|
517
|
-
}
|
|
495
|
+
if (!noBrowser)
|
|
496
|
+
launchMsger(url);
|
|
518
497
|
return;
|
|
519
498
|
}
|
|
499
|
+
// Redirect console to log file — keep terminal clean
|
|
500
|
+
// Server also logs, but this catches CLI startup messages
|
|
501
|
+
if (!verbose) {
|
|
502
|
+
const home = process.env.USERPROFILE || process.env.HOME || ".";
|
|
503
|
+
const logDir = path.join(home, ".mailx", "logs");
|
|
504
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
505
|
+
const logDate = new Date().toISOString().slice(0, 10);
|
|
506
|
+
const logPath = path.join(logDir, `mailx-${logDate}.log`);
|
|
507
|
+
const logStream = fs.createWriteStream(logPath, { flags: "a" });
|
|
508
|
+
const origLog = console.log;
|
|
509
|
+
const origErr = console.error;
|
|
510
|
+
console.log = (...a) => { logStream.write(a.join(" ") + "\n"); };
|
|
511
|
+
console.error = (...a) => { logStream.write("ERROR " + a.join(" ") + "\n"); };
|
|
512
|
+
}
|
|
520
513
|
// Start Express server in-process
|
|
521
514
|
console.log("Starting mailx server...");
|
|
522
|
-
log(`Loading server from: ${path.join(import.meta.dirname, "..", "packages", "mailx-server", "index.js")}`);
|
|
523
515
|
if (hasFlag("external"))
|
|
524
516
|
process.argv.push("--external");
|
|
525
517
|
await import("../packages/mailx-server/index.js");
|
|
@@ -531,14 +523,7 @@ async function main() {
|
|
|
531
523
|
if (await isPortInUse(PORT))
|
|
532
524
|
break;
|
|
533
525
|
}
|
|
534
|
-
|
|
535
|
-
openBrowser(url);
|
|
536
|
-
console.log("mailx opened (browser)");
|
|
537
|
-
}
|
|
538
|
-
else {
|
|
539
|
-
launchMsger(url);
|
|
540
|
-
console.log("mailx opened");
|
|
541
|
-
}
|
|
526
|
+
launchMsger(url);
|
|
542
527
|
}
|
|
543
528
|
// Keep process alive — server is running
|
|
544
529
|
await new Promise(() => { });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.141",
|
|
4
4
|
"description": "Local-first email client with IMAP sync and standalone native app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/mailx.js",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"start": "node --watch packages/mailx-server/index.js",
|
|
18
18
|
"start:prod": "node packages/mailx-server/index.js",
|
|
19
19
|
"release": "npmglobalize",
|
|
20
|
-
"postinstall": "node
|
|
20
|
+
"postinstall": "node bin/postinstall.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@bobfrankston/iflow": "^1.0.52",
|
|
24
24
|
"@bobfrankston/miscinfo": "^1.0.7",
|
|
25
25
|
"@bobfrankston/oauthsupport": "^1.0.20",
|
|
26
|
-
"@bobfrankston/
|
|
26
|
+
"@bobfrankston/msger": "^0.1.195",
|
|
27
27
|
"@capacitor/android": "^8.3.0",
|
|
28
28
|
"@capacitor/cli": "^8.3.0",
|
|
29
29
|
"@capacitor/core": "^8.3.0",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@bobfrankston/iflow": "file:../MailApps/iflow",
|
|
58
58
|
"@bobfrankston/miscinfo": "file:../../projects/npm/miscinfo",
|
|
59
59
|
"@bobfrankston/oauthsupport": "file:../../projects/oauth/oauthsupport",
|
|
60
|
-
"@bobfrankston/
|
|
60
|
+
"@bobfrankston/msger": "file:../../utils/msgx/msger",
|
|
61
61
|
"@capacitor/android": "^8.3.0",
|
|
62
62
|
"@capacitor/cli": "^8.3.0",
|
|
63
63
|
"@capacitor/core": "^8.3.0",
|
|
@@ -9,7 +9,7 @@ import * as fs from "node:fs";
|
|
|
9
9
|
import { MailxDB } from "@bobfrankston/mailx-store";
|
|
10
10
|
import { ImapManager } from "@bobfrankston/mailx-imap";
|
|
11
11
|
import { createApiRouter } from "@bobfrankston/mailx-api";
|
|
12
|
-
import { loadSettings, loadAccountsAsync, getConfigDir, getStorePath, getStorageInfo
|
|
12
|
+
import { loadSettings, loadAccountsAsync, getConfigDir, getStorePath, getStorageInfo } from "@bobfrankston/mailx-settings";
|
|
13
13
|
import { ports } from "@bobfrankston/miscinfo";
|
|
14
14
|
import { createServer } from "node:http";
|
|
15
15
|
const PORT = ports.mailx;
|
|
@@ -45,7 +45,8 @@ console.error = (...args) => {
|
|
|
45
45
|
const rootPkg = JSON.parse(fs.readFileSync(path.join(import.meta.dirname, "..", "..", "package.json"), "utf-8"));
|
|
46
46
|
const SERVER_VERSION = rootPkg.version;
|
|
47
47
|
// ── Initialize ──
|
|
48
|
-
initLocalConfig()
|
|
48
|
+
// No initLocalConfig() here — config is created when user adds an account (initCloudConfig).
|
|
49
|
+
// On fresh install, loadSettings() returns defaults and the setup form handles configuration.
|
|
49
50
|
let settings = loadSettings();
|
|
50
51
|
if (settings.accounts.length === 0) {
|
|
51
52
|
// Try cloud API fallback (Google Drive, OneDrive) if filesystem mount not available
|
|
Binary file
|
|
Binary file
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* mailx postinstall:
|
|
4
|
-
* 1. Link workspace packages so Node can resolve them after npm install
|
|
5
|
-
* 2. Set binary permissions on Linux/Mac
|
|
6
|
-
*/
|
|
7
|
-
import fs from "node:fs";
|
|
8
|
-
import path from "node:path";
|
|
9
|
-
import { fileURLToPath } from "url";
|
|
10
|
-
|
|
11
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
const root = path.join(__dirname, "..", "..");
|
|
13
|
-
|
|
14
|
-
// Link workspace packages into node_modules so imports resolve
|
|
15
|
-
const nodeModules = path.join(root, "node_modules", "@bobfrankston");
|
|
16
|
-
const packagesDir = path.join(root, "packages");
|
|
17
|
-
if (fs.existsSync(packagesDir)) {
|
|
18
|
-
fs.mkdirSync(nodeModules, { recursive: true });
|
|
19
|
-
for (const pkg of fs.readdirSync(packagesDir)) {
|
|
20
|
-
const pkgDir = path.join(packagesDir, pkg);
|
|
21
|
-
const pkgJson = path.join(pkgDir, "package.json");
|
|
22
|
-
if (!fs.existsSync(pkgJson)) continue;
|
|
23
|
-
try {
|
|
24
|
-
const meta = JSON.parse(fs.readFileSync(pkgJson, "utf-8"));
|
|
25
|
-
const name = meta.name?.replace("@bobfrankston/", "");
|
|
26
|
-
if (!name) continue;
|
|
27
|
-
const link = path.join(nodeModules, name);
|
|
28
|
-
// Remove stale junction/symlink that may point to wrong location
|
|
29
|
-
try { fs.unlinkSync(link); } catch { try { fs.rmSync(link, { recursive: true }); } catch { /* */ } }
|
|
30
|
-
// Create junction (Windows) or symlink (Unix) to local packages dir
|
|
31
|
-
if (process.platform === "win32") {
|
|
32
|
-
fs.symlinkSync(pkgDir, link, "junction");
|
|
33
|
-
} else {
|
|
34
|
-
fs.symlinkSync(pkgDir, link, "dir");
|
|
35
|
-
}
|
|
36
|
-
} catch { /* skip */ }
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Set binary permissions
|
|
41
|
-
try {
|
|
42
|
-
const { runPostinstall } = await import("@bobfrankston/rust-builder/postinstall");
|
|
43
|
-
const path = await import("path");
|
|
44
|
-
const { fileURLToPath } = await import("url");
|
|
45
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
46
|
-
|
|
47
|
-
runPostinstall({
|
|
48
|
-
binaryName: "mailx-app",
|
|
49
|
-
binDir: path.join(__dirname, "..", "bin"),
|
|
50
|
-
binaries: {
|
|
51
|
-
win32: "mailx-app.exe",
|
|
52
|
-
darwin: "mailx-app",
|
|
53
|
-
darwinArm64: "mailx-app-arm64",
|
|
54
|
-
linux: "mailx-app-linux",
|
|
55
|
-
linuxArm64: "mailx-app-linux-aarch64",
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
} catch {
|
|
59
|
-
// rust-builder not available (e.g., local dev with file: deps)
|
|
60
|
-
// On Windows, nothing to do. On Linux/Mac, try chmod directly.
|
|
61
|
-
if (process.platform !== "win32") {
|
|
62
|
-
const fs = await import("fs");
|
|
63
|
-
const path = await import("path");
|
|
64
|
-
const { fileURLToPath } = await import("url");
|
|
65
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
66
|
-
const arch = process.arch;
|
|
67
|
-
const name = process.platform === "darwin"
|
|
68
|
-
? (arch === "arm64" ? "mailx-app-arm64" : "mailx-app")
|
|
69
|
-
: (arch === "arm64" ? "mailx-app-linux-aarch64" : "mailx-app-linux");
|
|
70
|
-
const bin = path.join(__dirname, "..", "bin", name);
|
|
71
|
-
try { fs.chmodSync(bin, 0o755); } catch { /* binary may not exist */ }
|
|
72
|
-
}
|
|
73
|
-
}
|
package/launcher/mailx.ico
DELETED
|
Binary file
|