@bobfrankston/mailx 1.0.16 → 1.0.18

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/client/app.js CHANGED
@@ -309,6 +309,19 @@ window.addEventListener("message", (e) => {
309
309
  if (e.data?.type === "openLink" && e.data.url) {
310
310
  window.open(e.data.url, "_blank", "noopener,noreferrer");
311
311
  }
312
+ if (e.data?.type === "linkHover") {
313
+ const statusEl = document.getElementById("status-sync");
314
+ if (statusEl) {
315
+ if (e.data.url) {
316
+ statusEl.textContent = e.data.url;
317
+ statusEl.style.color = "var(--color-text-muted)";
318
+ }
319
+ else {
320
+ statusEl.textContent = "";
321
+ statusEl.style.color = "";
322
+ }
323
+ }
324
+ }
312
325
  });
313
326
  // ── Splitter drag ──
314
327
  const splitter = document.getElementById("splitter-h");
@@ -265,7 +265,7 @@ function wrapHtmlBody(html, allowRemote = false) {
265
265
  // CSP blocks remote resource loading (tracking pixels, external CSS) but allows link clicks
266
266
  const csp = allowRemote
267
267
  ? ""
268
- : `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data: cid:; form-action 'none';">`;
268
+ : `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: cid:; form-action 'none';">`;
269
269
  return `<!DOCTYPE html>
270
270
  <html><head>
271
271
  <meta charset="UTF-8">
@@ -293,6 +293,12 @@ ${csp}
293
293
  }
294
294
  </style>
295
295
  <base target="_blank">
296
+ <script>
297
+ document.addEventListener("mouseover", e => {
298
+ const a = e.target.closest("a[href]");
299
+ window.parent.postMessage({ type: "linkHover", url: a ? a.href : "" }, "*");
300
+ });
301
+ </script>
296
302
  </head><body>${html}</body></html>`;
297
303
  }
298
304
  //# sourceMappingURL=message-viewer.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -61,7 +61,6 @@
61
61
  "express": "^4.21.0",
62
62
  "nodemailer": "^7.0.0",
63
63
  "ws": "^8.18.0",
64
- "jsonc-parser": "^3.3.1",
65
- "better-sqlite3": "^11.7.0"
64
+ "jsonc-parser": "^3.3.1"
66
65
  }
67
66
  }
@@ -3,7 +3,7 @@
3
3
  * Stores message headers, folder structure, sync state.
4
4
  * Message bodies are NOT here -- they live in the MessageStore backend.
5
5
  */
6
- import Database from "better-sqlite3";
6
+ import { DatabaseSync } from "node:sqlite";
7
7
  import * as path from "node:path";
8
8
  import * as fs from "node:fs";
9
9
  const SCHEMA = `
@@ -118,9 +118,9 @@ export class MailxDB {
118
118
  constructor(dbDir) {
119
119
  fs.mkdirSync(dbDir, { recursive: true });
120
120
  const dbPath = path.join(dbDir, "mailx.db");
121
- this.db = new Database(dbPath);
122
- this.db.pragma("journal_mode = WAL");
123
- this.db.pragma("foreign_keys = ON");
121
+ this.db = new DatabaseSync(dbPath);
122
+ this.db.exec("PRAGMA journal_mode = WAL");
123
+ this.db.exec("PRAGMA foreign_keys = ON");
124
124
  this.db.exec(SCHEMA);
125
125
  }
126
126
  close() {
@@ -462,7 +462,8 @@ export class MailxDB {
462
462
  const insert = this.db.prepare("INSERT INTO messages_fts (rowid, subject, from_name, from_address, to_text, cc_text, body_text) VALUES (?, ?, ?, ?, ?, ?, ?)");
463
463
  const rows = this.db.prepare("SELECT id, subject, from_name, from_address, to_json, cc_json, preview FROM messages").all();
464
464
  let count = 0;
465
- const batchInsert = this.db.transaction(() => {
465
+ this.db.exec("BEGIN");
466
+ try {
466
467
  for (const r of rows) {
467
468
  const to = JSON.parse(r.to_json || "[]");
468
469
  const cc = JSON.parse(r.cc_json || "[]");
@@ -474,8 +475,12 @@ export class MailxDB {
474
475
  }
475
476
  catch { /* skip duplicates */ }
476
477
  }
477
- });
478
- batchInsert();
478
+ this.db.exec("COMMIT");
479
+ }
480
+ catch (e) {
481
+ this.db.exec("ROLLBACK");
482
+ throw e;
483
+ }
479
484
  return count;
480
485
  }
481
486
  // ── Sync Actions ──