@bobfrankston/rmfmail 1.2.136 → 1.2.137
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 +62 -6
- package/bin/mailx.js.map +1 -1
- package/bin/mailx.ts +58 -6
- package/client/app.bundle.js +40 -5
- package/client/app.bundle.js.map +3 -3
- package/client/app.js +31 -0
- package/client/app.js.map +1 -1
- package/client/app.ts +24 -0
- package/client/components/message-list.js +30 -4
- package/client/components/message-list.js.map +1 -1
- package/client/components/message-list.ts +30 -4
- package/client/compose/compose.bundle.js +4 -0
- package/client/compose/compose.bundle.js.map +2 -2
- package/client/lib/api-client.js +5 -0
- package/client/lib/api-client.js.map +1 -1
- package/client/lib/api-client.ts +6 -0
- package/client/lib/mailxapi.js +4 -0
- package/package.json +1 -1
- package/packages/mailx-service/jsonrpc.d.ts +1 -0
- package/packages/mailx-service/jsonrpc.d.ts.map +1 -1
- package/packages/mailx-service/jsonrpc.js +15 -0
- package/packages/mailx-service/jsonrpc.js.map +1 -1
- package/packages/mailx-service/jsonrpc.ts +17 -0
- package/packages/mailx-store/db.d.ts.map +1 -1
- package/packages/mailx-store/db.js +28 -2
- package/packages/mailx-store/db.js.map +1 -1
- package/packages/mailx-store/db.ts +27 -2
package/bin/mailx.js
CHANGED
|
@@ -1830,10 +1830,31 @@ async function main() {
|
|
|
1830
1830
|
const d = new Date();
|
|
1831
1831
|
return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}.${pad3(d.getMilliseconds())}`;
|
|
1832
1832
|
};
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1833
|
+
// Day-aware stream: recompute the filename on every write and swap
|
|
1834
|
+
// the stream at midnight. The old code resolved the path ONCE at
|
|
1835
|
+
// boot, so a daemon that ran past midnight kept appending to the
|
|
1836
|
+
// boot-day file forever — while the sync worker's lines (written
|
|
1837
|
+
// through its own channel) landed in the new day's file. Result: the
|
|
1838
|
+
// morning of 2026-07-14 had ALL main-thread diagnostics ([ipc],
|
|
1839
|
+
// [client], [popout]) hiding in rmfmail-2026-07-13.log and the
|
|
1840
|
+
// current file showing only [w] worker lines — which made the
|
|
1841
|
+
// popout-send data-loss incident look untraceable (S68).
|
|
1842
|
+
let logDate = localDate();
|
|
1843
|
+
let logStream = fs.createWriteStream(path.join(logDir, `rmfmail-${logDate}.log`), { flags: "a" });
|
|
1844
|
+
const logWrite = (line) => {
|
|
1845
|
+
const d = localDate();
|
|
1846
|
+
if (d !== logDate) {
|
|
1847
|
+
try {
|
|
1848
|
+
logStream.end();
|
|
1849
|
+
}
|
|
1850
|
+
catch { /* old handle already dead */ }
|
|
1851
|
+
logDate = d;
|
|
1852
|
+
logStream = fs.createWriteStream(path.join(logDir, `rmfmail-${d}.log`), { flags: "a" });
|
|
1853
|
+
}
|
|
1854
|
+
logStream.write(line);
|
|
1855
|
+
};
|
|
1856
|
+
console.log = (...a) => { logWrite(`${ts()} ${a.join(" ")}\n`); };
|
|
1857
|
+
console.error = (...a) => { logWrite(`${ts()} ERROR ${a.join(" ")}\n`); };
|
|
1837
1858
|
// Redirect daemon's process.stderr to the log too. msger forwards its
|
|
1838
1859
|
// Rust child's stderr to our process.stderr; in daemon mode that's
|
|
1839
1860
|
// stdio:"ignore" → /dev/null, which buries diagnostics like
|
|
@@ -1843,7 +1864,7 @@ async function main() {
|
|
|
1843
1864
|
process.stderr.write = ((chunk, ...rest) => {
|
|
1844
1865
|
try {
|
|
1845
1866
|
const s = typeof chunk === "string" ? chunk : chunk.toString();
|
|
1846
|
-
|
|
1867
|
+
logWrite(`${ts()} STDERR ${s}${s.endsWith("\n") ? "" : "\n"}`);
|
|
1847
1868
|
}
|
|
1848
1869
|
catch { /* ignore — best-effort logging */ }
|
|
1849
1870
|
return origStderrWrite(chunk, ...rest);
|
|
@@ -1858,7 +1879,7 @@ async function main() {
|
|
|
1858
1879
|
// for nothing — each was independent. Same for node-tcp-transport
|
|
1859
1880
|
// and mailx-store/file-store.js further down; folded in here so the
|
|
1860
1881
|
// resolution + module-init cost happens once, in parallel.
|
|
1861
|
-
const [{ MailxDB, prewarmParseWorker, storeBus, Store }, { ImapManager }, { MailxService, spawnSyncWorker }, { dispatch }, { loadSettings, loadAccountsAsync, loadAllowlistAsync, getConfigDir, getStorageInfo, getStorePath }, { NodeTcpTransport }, { FileMessageStore },] = await Promise.all([
|
|
1882
|
+
const [{ MailxDB, prewarmParseWorker, storeBus, Store }, { ImapManager }, { MailxService, spawnSyncWorker }, { dispatch, setDebugEvalSink }, { loadSettings, loadAccountsAsync, loadAllowlistAsync, getConfigDir, getStorageInfo, getStorePath }, { NodeTcpTransport }, { FileMessageStore },] = await Promise.all([
|
|
1862
1883
|
import("@bobfrankston/mailx-store"),
|
|
1863
1884
|
import("@bobfrankston/mailx-imap"),
|
|
1864
1885
|
import("@bobfrankston/mailx-service"),
|
|
@@ -2116,6 +2137,41 @@ RFC 5322 with CRLF line endings. Bodies are quoted-printable encoded (readable i
|
|
|
2116
2137
|
const { ports } = await import("@bobfrankston/miscinfo");
|
|
2117
2138
|
const dbgApp = express();
|
|
2118
2139
|
dbgApp.use(express.json({ limit: "25mb" }));
|
|
2140
|
+
// Live-page eval: POST /api/eval {code} → daemon pushes a
|
|
2141
|
+
// `debugEval` event to the main window → app.ts runs the code and
|
|
2142
|
+
// answers via the `debugEvalResult` action → we reply here. The
|
|
2143
|
+
// expression may be async (it's wrapped in `(async () => (…))()`),
|
|
2144
|
+
// must evaluate as an EXPRESSION, and should return JSON-able
|
|
2145
|
+
// data. Lets an agent inspect the real DOM (elementFromPoint,
|
|
2146
|
+
// computed styles, scroll geometry) without devtools. Registered
|
|
2147
|
+
// BEFORE the generic /api router so it isn't shadowed.
|
|
2148
|
+
const pendingEvals = new Map();
|
|
2149
|
+
setDebugEvalSink((id, result, error) => {
|
|
2150
|
+
const p = pendingEvals.get(id);
|
|
2151
|
+
if (!p)
|
|
2152
|
+
return;
|
|
2153
|
+
pendingEvals.delete(id);
|
|
2154
|
+
clearTimeout(p.timer);
|
|
2155
|
+
p.finish(error ? { error } : { result });
|
|
2156
|
+
});
|
|
2157
|
+
dbgApp.post("/api/eval", (req, res) => {
|
|
2158
|
+
const code = req.body?.code;
|
|
2159
|
+
if (typeof code !== "string" || !code.trim()) {
|
|
2160
|
+
res.status(400).json({ error: "body must be { code: string } — a JS expression" });
|
|
2161
|
+
return;
|
|
2162
|
+
}
|
|
2163
|
+
if (!sendToClient) {
|
|
2164
|
+
res.status(503).json({ error: "main window not connected yet" });
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
const id = `ev-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2168
|
+
const timer = setTimeout(() => {
|
|
2169
|
+
pendingEvals.delete(id);
|
|
2170
|
+
res.status(504).json({ error: "eval timeout (10s) — window busy, or client bundle predates debugEval" });
|
|
2171
|
+
}, 10_000);
|
|
2172
|
+
pendingEvals.set(id, { finish: (v) => res.json(v), timer });
|
|
2173
|
+
sendToClient({ _event: "debugEval", type: "debugEval", id, code });
|
|
2174
|
+
});
|
|
2119
2175
|
dbgApp.use("/api", createApiRouter(store, imapManager));
|
|
2120
2176
|
// Port: `--debug-server=<n>` / `--debug-server <n>` if given,
|
|
2121
2177
|
// else the reserved `ports.rmfmaildbg` from miscinfo (the named
|