@bobfrankston/mailx-imap 0.1.27 → 0.1.28

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/index.js +29 -13
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -1949,24 +1949,40 @@ export class ImapManager extends EventEmitter {
1949
1949
  static RECONCILE_DELETE_GRACE_MS = 30 * 60_000;
1950
1950
  scheduleDeferredReconcileDelete(accountId, folderId, uid, folderPath) {
1951
1951
  const key = `${accountId}:${folderId}:${uid}`;
1952
- // If already pending, don't reset — the 60s clock should run from
1953
- // the FIRST detection so a flapping server can't keep deferring.
1952
+ // If already pending, don't reset — the grace clock runs from the
1953
+ // FIRST detection so a flapping server can't keep deferring.
1954
1954
  if (this.deferredDeletes.has(key))
1955
1955
  return;
1956
1956
  const t = setTimeout(() => {
1957
1957
  this.deferredDeletes.delete(key);
1958
- // Verify the row still exists at the original (folder, uid).
1959
- // If move-detect rebound it during the grace window, this
1960
- // lookup returns null skip the delete.
1961
- const env = this.db.getMessageByUid(accountId, uid, folderId);
1962
- if (!env || env.folderId !== folderId) {
1963
- console.log(` [reconcile-skip] ${accountId}/${folderPath} uid=${uid}: row moved during grace window (rebound to folder ${env?.folderId ?? "deleted"})`);
1964
- return;
1958
+ // NEW SEMANTICS (post-message_folders refactor): we drop the
1959
+ // FOLDER MEMBERSHIP, not the messages row. The message itself
1960
+ // may exist in other folders (Gmail labels, server-side moves
1961
+ // already reconciled by the dest folder's sync); deleting the
1962
+ // messages row would clobber those.
1963
+ //
1964
+ // 1. Delete from message_folders for THIS (folder, uid).
1965
+ // 2. Look up if the messages row has any other memberships.
1966
+ // If yes — message lives elsewhere; just drop our row's
1967
+ // body-cache reference if it was tied to this location.
1968
+ // If no — message is truly orphaned; delete the messages
1969
+ // row + unlink body file.
1970
+ const ds = this.db.dropFolderMembership?.(accountId, folderId, uid, folderPath);
1971
+ // Fall back to the legacy path if the new method isn't there
1972
+ // for some reason (defensive — shouldn't happen, but the same
1973
+ // call site is hit by Gmail-API reconcile too which I haven't
1974
+ // converted yet).
1975
+ if (!ds) {
1976
+ const env = this.db.getMessageByUid(accountId, uid, folderId);
1977
+ if (!env || env.folderId !== folderId) {
1978
+ console.log(` [reconcile-skip] ${accountId}/${folderPath} uid=${uid}: row moved during grace window`);
1979
+ return;
1980
+ }
1981
+ const tag = env.messageId ? `msgid=${env.messageId} subj="${(env.subject || "").slice(0, 60)}"` : "no-msgid";
1982
+ console.log(` [reconcile-delete] ${accountId}/${folderPath} uid=${uid} ${tag} (legacy path)`);
1983
+ this.unlinkBodyFile(accountId, uid, folderId).catch(() => { });
1984
+ this.db.deleteMessage(accountId, uid, "reconcile: server missing this UID after grace (legacy)", `mailx-imap deferred reconcile (${folderPath})`);
1965
1985
  }
1966
- const tag = env.messageId ? `msgid=${env.messageId} subj="${(env.subject || "").slice(0, 60)}"` : "no-msgid";
1967
- console.log(` [reconcile-delete] ${accountId}/${folderPath} uid=${uid} ${tag} (after 60s grace, no rebind)`);
1968
- this.unlinkBodyFile(accountId, uid, folderId).catch(() => { });
1969
- this.db.deleteMessage(accountId, uid, "reconcile: server missing this UID 60s after detection (no move-detect rebind)", `mailx-imap syncFolder deferred reconcile (${folderPath})`);
1970
1986
  this.db.recalcFolderCounts(folderId);
1971
1987
  this.emit("folderCountsChanged", accountId, {});
1972
1988
  }, ImapManager.RECONCILE_DELETE_GRACE_MS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx-imap",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -11,7 +11,7 @@
11
11
  "dependencies": {
12
12
  "@bobfrankston/mailx-types": "^0.1.10",
13
13
  "@bobfrankston/mailx-settings": "^0.1.13",
14
- "@bobfrankston/mailx-store": "^0.1.12",
14
+ "@bobfrankston/mailx-store": "^0.1.13",
15
15
  "@bobfrankston/iflow-direct": "^0.1.35",
16
16
  "@bobfrankston/tcp-transport": "^0.1.5",
17
17
  "@bobfrankston/smtp-direct": "^0.1.5",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@bobfrankston/mailx-types": "^0.1.10",
41
41
  "@bobfrankston/mailx-settings": "^0.1.13",
42
- "@bobfrankston/mailx-store": "^0.1.12",
42
+ "@bobfrankston/mailx-store": "^0.1.13",
43
43
  "@bobfrankston/iflow-direct": "^0.1.35",
44
44
  "@bobfrankston/tcp-transport": "^0.1.5",
45
45
  "@bobfrankston/smtp-direct": "^0.1.5",