@remit/backend 0.0.74 → 0.0.75

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/backend",
3
- "version": "0.0.74",
3
+ "version": "0.0.75",
4
4
  "description": "Remit Mail Inspector API backend",
5
5
  "license": "MIT",
6
6
  "author": "",
@@ -1,8 +1,17 @@
1
1
  import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
2
+ import { afterEach, describe, it } from "node:test";
3
3
  import type { MailboxItem } from "@remit/data-ports";
4
4
  import { MailboxSyncStatus } from "@remit/domain-enums";
5
- import { excludeDeletingMailboxes } from "./mailbox.js";
5
+ import { UnconfirmedTrashMailboxError } from "@remit/mailbox-service";
6
+ import type { APIGatewayProxyEvent } from "aws-lambda";
7
+ import type { Context } from "openapi-backend";
8
+ import { deriveAccountConfigId } from "../auth.js";
9
+ import {
10
+ _resetForTest,
11
+ type RemitClient,
12
+ setClient,
13
+ } from "../service/data-client.js";
14
+ import { excludeDeletingMailboxes, TrashOperations } from "./mailbox.js";
6
15
 
7
16
  const mailbox = (
8
17
  over: Partial<MailboxItem> & { mailboxId: string },
@@ -32,3 +41,58 @@ describe("excludeDeletingMailboxes", () => {
32
41
  );
33
42
  });
34
43
  });
44
+
45
+ const SUB = "cognito-sub-887";
46
+ const ACCOUNT_ID = "acc-887";
47
+
48
+ const emptyTrash = TrashOperations.TrashOperations_emptyTrash as unknown as (
49
+ context: Context,
50
+ event: APIGatewayProxyEvent,
51
+ ) => Promise<{ deletedCount: number }>;
52
+
53
+ const callEmptyTrash = (
54
+ serviceEmptyTrash: () => Promise<{ deletedCount: number }>,
55
+ ): Promise<{ deletedCount: number }> => {
56
+ setClient({
57
+ account: {
58
+ get: async () => ({
59
+ accountId: ACCOUNT_ID,
60
+ accountConfigId: deriveAccountConfigId(SUB),
61
+ }),
62
+ },
63
+ messageMove: { emptyTrash: serviceEmptyTrash },
64
+ } as unknown as RemitClient);
65
+
66
+ return emptyTrash(
67
+ { request: { params: { accountId: ACCOUNT_ID } } } as unknown as Context,
68
+ {
69
+ requestContext: { authorizer: { claims: { sub: SUB } } },
70
+ } as unknown as APIGatewayProxyEvent,
71
+ );
72
+ };
73
+
74
+ describe("TrashOperations_emptyTrash", () => {
75
+ afterEach(() => {
76
+ _resetForTest();
77
+ });
78
+
79
+ it("reports the service's count rather than one of its own", async () => {
80
+ // The handler resolves no folder and counts no rows: a second read would
81
+ // be free to disagree with the one that actually marked them.
82
+ const response = await callEmptyTrash(async () => ({ deletedCount: 7 }));
83
+
84
+ assert.deepEqual(response, { deletedCount: 7 });
85
+ });
86
+
87
+ it("lets the service's coded refusal through untouched", async () => {
88
+ await assert.rejects(
89
+ callEmptyTrash(async () => {
90
+ throw new UnconfirmedTrashMailboxError(ACCOUNT_ID);
91
+ }),
92
+ (error: unknown) =>
93
+ error instanceof UnconfirmedTrashMailboxError &&
94
+ error.statusCode === 409 &&
95
+ error.publicApiError?.details?.reason === "unconfirmed",
96
+ );
97
+ });
98
+ });
@@ -5,7 +5,6 @@ import type {
5
5
  import type { IAccountSettingRepository, MailboxItem } from "@remit/data-ports";
6
6
  import { ForbiddenError, NotFoundError } from "@remit/data-ports/errors";
7
7
  import { MailboxSyncStatus, MessageSystemFlag } from "@remit/domain-enums";
8
- import { NoTrashMailboxError } from "@remit/mailbox-service";
9
8
  import type { APIGatewayProxyEvent } from "aws-lambda";
10
9
  import { getAccountConfigIdFromEvent } from "../auth.js";
11
10
  import {
@@ -412,26 +411,10 @@ export const TrashOperations: Record<
412
411
  const account = await client.account.get(accountId);
413
412
  assertAccountOwnership(account, accountConfigId, "act");
414
413
 
415
- // The same confirmed resolution `emptyTrash` expunges through, so the
416
- // count reported is the count of the folder that gets emptied. It
417
- // refuses rather than returning zero when no folder is appointed and
418
- // none is flagged: "0 deleted" reads as success, and the user goes on
419
- // believing their Trash is empty.
420
- const trashMailbox =
421
- await client.mailboxSpecialUse.findConfirmedTrashMailbox(accountId);
422
-
423
- if (!trashMailbox) {
424
- throw new NoTrashMailboxError(accountId);
425
- }
426
-
427
- const messages = await client.message.listAllByMailbox(
428
- trashMailbox.mailboxId,
429
- );
430
- const deletedCount = messages.length;
431
-
432
- // MessageMoveService handles: Message status updates + SQS event
433
- await client.messageMove.emptyTrash(accountConfigId, accountId);
434
-
435
- return { deletedCount };
414
+ // The service resolves Trash, marks the rows and counts them, all off one
415
+ // read, and refuses with a coded 409 when the role is unresolved. Counting
416
+ // here as well would be a second answer free to disagree with the one that
417
+ // acts, and "0 deleted" reads as success to a user whose Trash is untouched.
418
+ return client.messageMove.emptyTrash(accountConfigId, accountId);
436
419
  },
437
420
  };