@remit/mailbox-service 0.0.67 → 0.0.69

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.69",
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);
@@ -201,6 +201,15 @@ describe("what a mailbox says about the addresses on its messages", () => {
201
201
  assert.deepEqual(emails(saved.envelopeAddresses), BOTH);
202
202
  });
203
203
 
204
+ it("leaves the identity of an envelope address to the store", async () => {
205
+ const saved = await save(mailboxAt("INBOX"));
206
+
207
+ assert.ok(saved.envelopeAddresses.length > 0);
208
+ for (const envelopeAddress of saved.envelopeAddresses) {
209
+ assert.ok(!("envelopeAddressId" in envelopeAddress));
210
+ }
211
+ });
212
+
204
213
  it("keeps a message in Trash from deciding either way", async () => {
205
214
  const saved = await save(mailboxAt("Trash"), "Trash");
206
215
 
@@ -16,7 +16,6 @@ import { storedDisplayName } from "@remit/data-ports/display-name";
16
16
  import {
17
17
  deriveAddressId,
18
18
  deriveBodyPartId,
19
- deriveEnvelopeAddressId,
20
19
  deriveEnvelopeId,
21
20
  deriveMessageIdFromSource,
22
21
  deriveThreadId,
@@ -1506,8 +1505,6 @@ export class MessageSyncService {
1506
1505
 
1507
1506
  const addressId = deriveAddressId(accountConfigId, normalizedEmail);
1508
1507
 
1509
- const envelopeAddressId = deriveEnvelopeAddressId(messageId, role, order);
1510
-
1511
1508
  const addressInput = {
1512
1509
  addressId,
1513
1510
  accountConfigId,
@@ -1526,7 +1523,6 @@ export class MessageSyncService {
1526
1523
  }
1527
1524
 
1528
1525
  await addressService.upsertEnvelopeAddress({
1529
- envelopeAddressId,
1530
1526
  messageId,
1531
1527
  addressId,
1532
1528
  displayName,