@bobfrankston/mailx-store 0.1.10 → 0.1.11

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/db.js +23 -5
  2. package/package.json +3 -3
package/db.js CHANGED
@@ -334,6 +334,25 @@ export class MailxDB {
334
334
  // this column landed. One UPDATE + an id roundtrip per row — cheap
335
335
  // at our row counts, runs once per DB upgrade.
336
336
  this.backfillUuids();
337
+ // One-shot cleanup: the retired insertOptimisticSentRow path wrote
338
+ // synthetic-negative-UID rows into Sent. Those rows are stale (the
339
+ // real server-synced row eventually appears with a positive UID),
340
+ // they pollute MAX(uid) (which broke Sent sync entirely), and the
341
+ // mechanism is gone. Drop them. Bodies on disk are orphaned; the
342
+ // body-store has no GC today but a one-time leak is fine.
343
+ try {
344
+ const purgedFlag = this.getKv("schema", "drop_synthetic_uids_v1");
345
+ if (!purgedFlag) {
346
+ const r = this.db.prepare("DELETE FROM messages WHERE uid < 0").run();
347
+ if (r.changes) {
348
+ console.log(` [migration] dropped ${r.changes} synthetic-UID rows from messages`);
349
+ }
350
+ this.setKv("schema", "drop_synthetic_uids_v1", "1");
351
+ }
352
+ }
353
+ catch (e) {
354
+ console.error(` [migration] synthetic-UID cleanup failed: ${e?.message || e}`);
355
+ }
337
356
  // One-shot contacts table reset: the contacts schema's UNIQUE constraint
338
357
  // was widened from `(email)` to `(source, email, name)` so the same
339
358
  // address can carry multiple distinct (name, source) entries — Bob's
@@ -1029,15 +1048,14 @@ export class MailxDB {
1029
1048
  // LEFT JOIN sync_actions so each row carries a `pending` flag —
1030
1049
  // true when the user has a queued local action (move/flag/delete)
1031
1050
  // not yet acknowledged by the server. UI renders these in pink so
1032
- // local-only state is visible (Slice C of S1). Negative UIDs also
1033
- // count as pending: that's the convention for optimistic local
1034
- // inserts (e.g. Sent rows written the moment the user hits Send,
1035
- // before the real APPENDUID comes back from the server).
1051
+ // local-only state is visible (Slice C of S1). The optimistic-Sent
1052
+ // negative-UID convention was retired Sent now reflects only what
1053
+ // the server has; pending sends live in the Outbox view.
1036
1054
  const rows = this.db.prepare(`SELECT m.*, (
1037
1055
  EXISTS(
1038
1056
  SELECT 1 FROM sync_actions sa
1039
1057
  WHERE sa.account_id = m.account_id AND sa.uid = m.uid
1040
- ) OR m.uid < 0
1058
+ )
1041
1059
  ) AS pending
1042
1060
  FROM messages m WHERE ${where.replace(/\b(account_id|folder_id|uid|date|subject|from_name|from_address|flags_json)\b/g, "m.$1")}
1043
1061
  ORDER BY m.${sortCol} ${sortDir} LIMIT ? OFFSET ?`).all(...params, pageSize, offset);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx-store",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -10,7 +10,7 @@
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "@bobfrankston/mailx-types": "^0.1.10",
13
- "@bobfrankston/mailx-settings": "^0.1.12"
13
+ "@bobfrankston/mailx-settings": "^0.1.13"
14
14
  },
15
15
  "repository": {
16
16
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  ".transformedSnapshot": {
27
27
  "dependencies": {
28
28
  "@bobfrankston/mailx-types": "^0.1.10",
29
- "@bobfrankston/mailx-settings": "^0.1.12"
29
+ "@bobfrankston/mailx-settings": "^0.1.13"
30
30
  }
31
31
  }
32
32
  }