@remit/mailbox-service 0.0.67 → 0.0.68

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/mailbox-service",
3
- "version": "0.0.67",
3
+ "version": "0.0.68",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -49,7 +49,9 @@ interface TrashMessage {
49
49
 
50
50
  interface EnqueuedEvent {
51
51
  type: string;
52
+ schemaVersion?: number;
52
53
  trashMailboxId?: string;
54
+ trashUidValidity?: number;
53
55
  }
54
56
 
55
57
  const buildWorld = (
@@ -87,7 +89,12 @@ const buildWorld = (
87
89
 
88
90
  const config: MessageMoveConfig = {
89
91
  messageService,
90
- mailboxService: {} as unknown as IMailboxRepository,
92
+ mailboxService: {
93
+ get: async (_accountId: string, mailboxId: string) => ({
94
+ mailboxId,
95
+ uidValidity: 42,
96
+ }),
97
+ } as unknown as IMailboxRepository,
91
98
  addressService: {
92
99
  reconcileJunkOnlyForMessage: async () => {},
93
100
  } as unknown as IAddressRepository,
@@ -220,4 +227,16 @@ describe("MessageMoveService.emptyTrash", () => {
220
227
  ["EMPTY_TRASH", "EMPTY_TRASH"],
221
228
  );
222
229
  });
230
+
231
+ it("carries the folder's identity as it stood at consent time", async () => {
232
+ // The worker compares this against what its own SELECT serves. Without
233
+ // it the expunge would be authorised by a path, and a path is reusable.
234
+ const { service, events } = buildWorld(appointedTrash);
235
+
236
+ await service.emptyTrash(ACCOUNT_CONFIG, ACCOUNT);
237
+
238
+ assert.equal(events[0]?.schemaVersion, 2);
239
+ assert.equal(events[0]?.trashMailboxId, REAL_TRASH);
240
+ assert.equal(events[0]?.trashUidValidity, 42);
241
+ });
223
242
  });
@@ -22,6 +22,7 @@ import {
22
22
  UNCONFIRMED_TRASH_FOLDER_REASON,
23
23
  } from "@remit/data-ports/folder-role";
24
24
  import { deriveCopyMessageId } from "@remit/data-ports/id";
25
+ import { MUTATION_EVENT_SCHEMA_VERSION } from "@remit/data-ports/mutation-events";
25
26
  import {
26
27
  CanonicalMailboxRole,
27
28
  MessageStatus,
@@ -35,6 +36,7 @@ import { createQueueProducer } from "@remit/sqs-client/producer";
35
36
  */
36
37
  interface MessageDeleteEvent {
37
38
  type: "MESSAGE_DELETE";
39
+ schemaVersion: typeof MUTATION_EVENT_SCHEMA_VERSION;
38
40
  eventId: string;
39
41
  timestamp: number;
40
42
  accountId: string;
@@ -62,11 +64,14 @@ interface MessageMoveEvent {
62
64
 
63
65
  interface EmptyTrashEvent {
64
66
  type: "EMPTY_TRASH";
67
+ schemaVersion: typeof MUTATION_EVENT_SCHEMA_VERSION;
65
68
  eventId: string;
66
69
  timestamp: number;
67
70
  accountId: string;
68
71
  trashMailboxId: string;
69
72
  trashMailboxPath: string;
73
+ /** The folder's UIDVALIDITY at consent time; the worker re-checks it. */
74
+ trashUidValidity: number;
70
75
  }
71
76
 
72
77
  interface MessageCopyEvent {
@@ -382,6 +387,7 @@ export class MessageMoveService {
382
387
 
383
388
  events.push({
384
389
  type: "MESSAGE_DELETE",
390
+ schemaVersion: MUTATION_EVENT_SCHEMA_VERSION,
385
391
  eventId: randomUUID(),
386
392
  timestamp: Date.now(),
387
393
  accountId,
@@ -425,6 +431,7 @@ export class MessageMoveService {
425
431
 
426
432
  events.push({
427
433
  type: "MESSAGE_DELETE",
434
+ schemaVersion: MUTATION_EVENT_SCHEMA_VERSION,
428
435
  eventId: randomUUID(),
429
436
  timestamp: Date.now(),
430
437
  accountId,
@@ -764,6 +771,15 @@ export class MessageMoveService {
764
771
  accountId,
765
772
  );
766
773
 
774
+ // The identity the user consented to, carried on the event so the worker
775
+ // can tell this folder from a different one that has since taken over its
776
+ // path. Read here rather than re-read there: the value at consent time is
777
+ // the whole point, and the stored row is rewritten by every sync.
778
+ const { uidValidity: trashUidValidity } = await this.mailboxService.get(
779
+ accountId,
780
+ trashMailbox.mailboxId,
781
+ );
782
+
767
783
  const messages = await this.messageService.listAllByMailbox(
768
784
  trashMailbox.mailboxId,
769
785
  );
@@ -793,11 +809,13 @@ export class MessageMoveService {
793
809
  // Enqueue single event for worker to handle batch
794
810
  const event: EmptyTrashEvent = {
795
811
  type: "EMPTY_TRASH",
812
+ schemaVersion: MUTATION_EVENT_SCHEMA_VERSION,
796
813
  eventId: randomUUID(),
797
814
  timestamp: Date.now(),
798
815
  accountId,
799
816
  trashMailboxId: trashMailbox.mailboxId,
800
817
  trashMailboxPath: trashMailbox.fullPath,
818
+ trashUidValidity,
801
819
  };
802
820
 
803
821
  await this.enqueueEvent(event);