@remit/imap-worker 0.0.30 → 0.0.32
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 +1 -1
- package/src/handlers/flag-push.test.ts +17 -2
- package/src/handlers/mailbox-management.test.ts +4 -0
- package/src/handlers/mailbox-management.ts +12 -9
- package/src/handlers/message-move.test.ts +13 -2
- package/src/handlers/placement-move-push.test.ts +17 -2
- package/src/handlers/sync-message-body.test.ts +2 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { afterEach, describe, it, mock } from "node:test";
|
|
3
|
-
import { getClient } from "@remit/backend/client";
|
|
2
|
+
import { afterEach, before, describe, it, mock } from "node:test";
|
|
3
|
+
import { getClient, type RemitClient, setClient } from "@remit/backend/client";
|
|
4
4
|
import type { Logger } from "@remit/logger-lambda";
|
|
5
5
|
import type { FlagPushEvent } from "../events.js";
|
|
6
6
|
import {
|
|
@@ -58,6 +58,21 @@ describe("handleFlagPush — deleted mailbox is terminal (#287/#289)", () => {
|
|
|
58
58
|
flagName,
|
|
59
59
|
} as FlagPushEvent;
|
|
60
60
|
|
|
61
|
+
// The client is supplied by injection (`setClient`), so these tests register
|
|
62
|
+
// the repositories they then mock rather than reaching a composition.
|
|
63
|
+
before(() => {
|
|
64
|
+
setClient({
|
|
65
|
+
account: { get: async () => undefined },
|
|
66
|
+
message: { get: async () => undefined },
|
|
67
|
+
mailbox: { get: async () => undefined },
|
|
68
|
+
flagPush: {
|
|
69
|
+
find: async () => undefined,
|
|
70
|
+
updateState: async () => undefined,
|
|
71
|
+
delete: async () => undefined,
|
|
72
|
+
},
|
|
73
|
+
} as unknown as RemitClient);
|
|
74
|
+
});
|
|
75
|
+
|
|
61
76
|
afterEach(() => mock.restoreAll());
|
|
62
77
|
|
|
63
78
|
it("drops the orphaned marker and acks without pushing when the mailbox is gone", async () => {
|
|
@@ -106,6 +106,10 @@ const deps = (): MailboxManagementDeps =>
|
|
|
106
106
|
h.calls.push({ method: "mailbox.update", args });
|
|
107
107
|
if (h.mailboxUpdateError) throw h.mailboxUpdateError;
|
|
108
108
|
},
|
|
109
|
+
findByPathPrefix: async (...args: unknown[]) => {
|
|
110
|
+
h.calls.push({ method: "mailbox.findByPathPrefix", args });
|
|
111
|
+
return [];
|
|
112
|
+
},
|
|
109
113
|
delete: record("mailbox.delete"),
|
|
110
114
|
},
|
|
111
115
|
secrets: {},
|
|
@@ -70,15 +70,18 @@ const isMailboxPresentUpstream = (error: unknown): boolean => {
|
|
|
70
70
|
* Pinned invariant for the whole-chain terminal guards below.
|
|
71
71
|
*
|
|
72
72
|
* Each handler wraps its `MailboxManagementService.sync*` chain in a try/catch
|
|
73
|
-
* that treats a NotFoundError as terminal (ack with a WARN, issue #289). That
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
73
|
+
* that treats a NotFoundError as terminal (ack with a WARN, issue #289). That is
|
|
74
|
+
* only sound while the sole row a NotFoundError can refer to is the target
|
|
75
|
+
* mailbox, so its absence can only mean the user deleted the folder mid-sync —
|
|
76
|
+
* never an unrelated missing entity that should have been retried.
|
|
77
|
+
*
|
|
78
|
+
* `syncCreate` and `syncDelete` hold to that by touching nothing but the target
|
|
79
|
+
* row. `syncRename` also writes the renamed subtree's descendant rows, and keeps
|
|
80
|
+
* the invariant by absorbing their NotFoundErrors itself: a descendant deleted
|
|
81
|
+
* mid-settle never reaches these catches. Any sync method that reads or writes a
|
|
82
|
+
* second entity owes the same, or these catches must be narrowed (match the
|
|
83
|
+
* mailboxId / re-check existence) before a NotFoundError from elsewhere is
|
|
84
|
+
* silently acked.
|
|
82
85
|
*/
|
|
83
86
|
|
|
84
87
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
|
-
import { afterEach, describe, it, mock } from "node:test";
|
|
3
|
-
import { getClient } from "@remit/backend/client";
|
|
2
|
+
import { afterEach, before, describe, it, mock } from "node:test";
|
|
3
|
+
import { getClient, type RemitClient, setClient } from "@remit/backend/client";
|
|
4
4
|
import type { AccountItem, ThreadMessageItem } from "@remit/data-ports";
|
|
5
5
|
import type { Logger } from "@remit/logger-lambda";
|
|
6
6
|
import type { MessageMoveEvent } from "../events.js";
|
|
@@ -219,6 +219,17 @@ describe("handleMessageMove — deleted mailbox is terminal (#287/#289)", () =>
|
|
|
219
219
|
timestamp: 1700000000000,
|
|
220
220
|
} as MessageMoveEvent;
|
|
221
221
|
|
|
222
|
+
// The client is supplied by injection (`setClient`), so these tests register
|
|
223
|
+
// the repositories they then mock rather than reaching a composition.
|
|
224
|
+
before(() => {
|
|
225
|
+
setClient({
|
|
226
|
+
account: { get: async () => undefined },
|
|
227
|
+
mailbox: { get: async () => undefined },
|
|
228
|
+
message: { updateUid: async () => undefined },
|
|
229
|
+
secrets: { decrypt: async () => undefined },
|
|
230
|
+
} as unknown as RemitClient);
|
|
231
|
+
});
|
|
232
|
+
|
|
222
233
|
afterEach(() => mock.restoreAll());
|
|
223
234
|
|
|
224
235
|
it("acks without connecting when the source mailbox was deleted", async () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { afterEach, describe, it, mock } from "node:test";
|
|
3
|
-
import { getClient } from "@remit/backend/client";
|
|
2
|
+
import { afterEach, before, describe, it, mock } from "node:test";
|
|
3
|
+
import { getClient, type RemitClient, setClient } from "@remit/backend/client";
|
|
4
4
|
import type { Logger } from "@remit/logger-lambda";
|
|
5
5
|
import type { IImapConnection } from "@remit/mailbox-service";
|
|
6
6
|
import type { PlacementMovePushEvent } from "../events.js";
|
|
@@ -295,6 +295,21 @@ describe("handlePlacementMovePush — deleted mailbox is terminal (#287/#289)",
|
|
|
295
295
|
timestamp: 1700000000000,
|
|
296
296
|
};
|
|
297
297
|
|
|
298
|
+
// The client is supplied by injection (`setClient`), so these tests register
|
|
299
|
+
// the repositories they then mock rather than reaching a composition.
|
|
300
|
+
before(() => {
|
|
301
|
+
setClient({
|
|
302
|
+
account: { get: async () => undefined },
|
|
303
|
+
message: { get: async () => undefined },
|
|
304
|
+
mailbox: { get: async () => undefined },
|
|
305
|
+
placementMove: {
|
|
306
|
+
find: async () => undefined,
|
|
307
|
+
updateState: async () => undefined,
|
|
308
|
+
delete: async () => undefined,
|
|
309
|
+
},
|
|
310
|
+
} as unknown as RemitClient);
|
|
311
|
+
});
|
|
312
|
+
|
|
298
313
|
afterEach(() => mock.restoreAll());
|
|
299
314
|
|
|
300
315
|
it("drops the marker and acks without pushing when a mailbox is gone", async () => {
|
|
@@ -221,10 +221,8 @@ describe("syncMessageBody — DLQ propagation (integrated, #1270)", () => {
|
|
|
221
221
|
const cappedMailbox = (): MailboxItem =>
|
|
222
222
|
({ fullPath: "INBOX" }) as unknown as MailboxItem;
|
|
223
223
|
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
// then mock. On the relational path (reader, DATA_BACKEND=postgres) getClient
|
|
227
|
-
// builds its own client and this injection is inert.
|
|
224
|
+
// The client is supplied by injection (`setClient`), so these tests register
|
|
225
|
+
// the repositories they then mock rather than reaching a composition.
|
|
228
226
|
before(() => {
|
|
229
227
|
setClient({
|
|
230
228
|
account: { get: async () => cappedAccount() },
|