@bobfrankston/mailx-sync 0.1.16 → 0.1.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.
Files changed (3) hide show
  1. package/gmail.d.ts +2 -2
  2. package/gmail.js +22 -8
  3. package/package.json +3 -3
package/gmail.d.ts CHANGED
@@ -63,11 +63,11 @@ export declare class GmailApiProvider implements MailProvider {
63
63
  * as a destination folder — `POST /messages/{id}/trash` is the native
64
64
  * path (equivalent to setting TRASH and removing INBOX in one op).
65
65
  * Used by mailx's delete/trash path. */
66
- trashMessage(folder: string, uid: number): Promise<void>;
66
+ trashMessage(folder: string, uid: number, gmailId?: string): Promise<void>;
67
67
  /** Move between "folders" == swap one label for another via modifyLabels.
68
68
  * System labels (INBOX/SENT/TRASH/SPAM) are translated from the folder
69
69
  * path; user labels use the folder path verbatim as the label id. */
70
- moveMessage(fromFolder: string, uid: number, toFolder: string): Promise<void>;
70
+ moveMessage(fromFolder: string, uid: number, toFolder: string, gmailId?: string): Promise<void>;
71
71
  /** Folder path → Gmail label id. System folders map to uppercase label
72
72
  * constants; anything else is treated as a user label (identical name). */
73
73
  private folderPathToLabelId;
package/gmail.js CHANGED
@@ -556,10 +556,19 @@ export class GmailApiProvider {
556
556
  * as a destination folder — `POST /messages/{id}/trash` is the native
557
557
  * path (equivalent to setting TRASH and removing INBOX in one op).
558
558
  * Used by mailx's delete/trash path. */
559
- async trashMessage(folder, uid) {
560
- const query = `in:${this.folderToLabel(folder)}`;
561
- const ids = await this.listMessageIds(query, 1000);
562
- const id = ids.find(id => idToUid(id) === uid);
559
+ async trashMessage(folder, uid, gmailId) {
560
+ // Prefer the caller-supplied Gmail message id (mailx stores it as
561
+ // `provider_id`). The fallback list the folder and hash-match the
562
+ // uid is capped at 1000, so on a large mailbox it CANNOT find a
563
+ // message past the most-recent ~1000: the trash then throws, the
564
+ // sync action fails its retries, and clearTombstoneForUid resurrects
565
+ // the message ("deletions un-happening", Bob 2026-05-17). Passing the
566
+ // stored id skips that broken search entirely.
567
+ let id = gmailId;
568
+ if (!id) {
569
+ const ids = await this.listMessageIds(`in:${this.folderToLabel(folder)}`, 1000);
570
+ id = ids.find(x => idToUid(x) === uid);
571
+ }
563
572
  if (!id)
564
573
  throw new Error(`Gmail trashMessage: UID ${uid} not found in ${folder}`);
565
574
  await this.fetch(`/messages/${id}/trash`, { method: "POST" });
@@ -567,10 +576,15 @@ export class GmailApiProvider {
567
576
  /** Move between "folders" == swap one label for another via modifyLabels.
568
577
  * System labels (INBOX/SENT/TRASH/SPAM) are translated from the folder
569
578
  * path; user labels use the folder path verbatim as the label id. */
570
- async moveMessage(fromFolder, uid, toFolder) {
571
- const query = `in:${this.folderToLabel(fromFolder)}`;
572
- const ids = await this.listMessageIds(query, 1000);
573
- const id = ids.find(id => idToUid(id) === uid);
579
+ async moveMessage(fromFolder, uid, toFolder, gmailId) {
580
+ // See trashMessage — prefer the caller's stored Gmail id; the
581
+ // list-and-hash fallback is capped at 1000 and breaks on large
582
+ // folders.
583
+ let id = gmailId;
584
+ if (!id) {
585
+ const ids = await this.listMessageIds(`in:${this.folderToLabel(fromFolder)}`, 1000);
586
+ id = ids.find(x => idToUid(x) === uid);
587
+ }
574
588
  if (!id)
575
589
  throw new Error(`Gmail moveMessage: UID ${uid} not found in ${fromFolder}`);
576
590
  // Map the folder path to the label id. System labels are uppercased
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx-sync",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Platform-agnostic mail provider implementations + sync orchestration. Single source of truth for Gmail/IMAP/Outlook protocol code, consumed by both desktop (Node) and Android (WebView) — eliminates the parallel mailx-imap/mailx-store-web Gmail providers that drifted in practice.",
5
5
  "main": "index.js",
6
6
  "types": "index.ts",
@@ -19,7 +19,7 @@
19
19
  "author": "Bob Frankston",
20
20
  "license": "ISC",
21
21
  "dependencies": {
22
- "@bobfrankston/iflow-direct": "^0.1.38",
22
+ "@bobfrankston/iflow-direct": "^0.1.50",
23
23
  "@bobfrankston/tcp-transport": "^0.1.6"
24
24
  },
25
25
  "exports": {
@@ -44,7 +44,7 @@
44
44
  },
45
45
  ".transformedSnapshot": {
46
46
  "dependencies": {
47
- "@bobfrankston/iflow-direct": "^0.1.38",
47
+ "@bobfrankston/iflow-direct": "^0.1.50",
48
48
  "@bobfrankston/tcp-transport": "^0.1.6"
49
49
  }
50
50
  }