@remit/mailbox-service 0.0.38 → 0.0.39

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/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # @remit/mailbox-service
2
2
 
3
- IMAP mailbox synchronization service for Remit. Provides connection management, mailbox discovery, and message sync with DynamoDB persistence.
3
+ IMAP mailbox synchronization service for Remit. Provides connection management, mailbox discovery, and message sync. Persistence is injected: the service takes repository ports, never a database client.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - **ImapFlow-based**: Modern async/await IMAP client with native envelope parsing
8
- - **Mailbox Sync**: Discovers and syncs mailbox metadata from IMAP to DynamoDB
8
+ - **Mailbox Sync**: Discovers and syncs mailbox metadata from IMAP into the mailbox repository
9
9
  - **Message Sync**: Newest-first sync strategy with dual-watermark tracking
10
10
  - **Address Extraction**: Parses and stores envelope addresses with role tracking
11
11
 
@@ -55,10 +55,11 @@ await connection.disconnect();
55
55
  ```typescript
56
56
  import { MailboxSyncService } from "@remit/mailbox-service";
57
57
 
58
- const syncService = new MailboxSyncService({
59
- client: dynamoDBClient,
60
- table: "remit-table",
61
- });
58
+ const syncService = new MailboxSyncService(
59
+ mailboxRepository,
60
+ mailboxSpecialUseRepository,
61
+ logger,
62
+ );
62
63
 
63
64
  const result = await syncService.syncMailboxes(
64
65
  { accountId: "acc-123" },
@@ -103,7 +104,7 @@ const synced = await messageSyncService.syncMessages(
103
104
 
104
105
  | Export | Description |
105
106
  | -------------------- | ----------------------------------------- |
106
- | `MailboxSyncService` | Syncs mailbox list from IMAP to DynamoDB |
107
+ | `MailboxSyncService` | Syncs mailbox list from IMAP into the store |
107
108
  | `MessageSyncService` | Syncs messages with newest-first strategy |
108
109
 
109
110
  ### Types
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/mailbox-service",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
package/src/body-parse.ts CHANGED
@@ -9,7 +9,7 @@ type FailureCode = QuarantineItem["failureCode"];
9
9
  *
10
10
  * This type is the whole reason the sync path can quarantine anything. Before
11
11
  * it, every catch site on the body path saw one undifferentiated `unknown`
12
- * covering mailparser, S3, DynamoDB and SQS alike, so "the message is built in
12
+ * covering mailparser, S3, the database and SQS alike, so "the message is built in
13
13
  * a way Remit could not read" was indistinguishable from "S3 returned a 503".
14
14
  * Recording the second as the first advances the cursor past mail that is
15
15
  * perfectly fine and never fetches it again.
@@ -33,8 +33,8 @@ export interface MailboxCursorGuardDeps {
33
33
  /**
34
34
  * `cursorState` is total per RFC 032 (defaults to `normal`) — but that default
35
35
  * only applies to rows written after this field existed. A row persisted
36
- * before this migration (DynamoDB attribute never written / Postgres column
37
- * genuinely NULL) reads back with the attribute absent despite the type
36
+ * before this migration (the column genuinely NULL) reads back absent
37
+ * despite the type
38
38
  * saying otherwise, so every consumer here treats `undefined` the same as
39
39
  * `normal` defensively rather than trusting the type.
40
40
  */
@@ -100,7 +100,7 @@ export const validateMailboxOperation = (
100
100
  * Service for managing mailbox operations (create, rename, delete).
101
101
  *
102
102
  * Implements an optimistic local-first pattern:
103
- * 1. Updates are applied locally first (DynamoDB)
103
+ * 1. Updates are applied locally first
104
104
  * 2. Changes are queued for IMAP sync via SQS
105
105
  * 3. Worker processes queue and syncs to IMAP server
106
106
  */
@@ -244,7 +244,7 @@ export class MailboxManagementService {
244
244
 
245
245
  this.log.info({ mailboxId, path }, "Deleted mailbox on IMAP server");
246
246
 
247
- // Delete the mailbox entity from DynamoDB
247
+ // Delete the mailbox entity from the local store
248
248
  await this.mailboxService.delete(accountId, mailboxId);
249
249
 
250
250
  return { success: true };
@@ -83,7 +83,7 @@ export interface MailboxQueueConfig {
83
83
  * Service for mailbox management with automatic IMAP sync queueing.
84
84
  *
85
85
  * Implements optimistic local-first pattern:
86
- * 1. Updates local DynamoDB state immediately
86
+ * 1. Updates local state immediately
87
87
  * 2. Enqueues mailbox management event to SQS for worker to sync to IMAP
88
88
  *
89
89
  * This follows the same pattern as FlagQueueService (RFC 014).
@@ -115,7 +115,7 @@ export interface DeleteOptions {
115
115
  * Service for moving, copying, and deleting messages.
116
116
  *
117
117
  * Implements optimistic local-first pattern:
118
- * 1. Updates local DynamoDB state immediately (Message + ThreadMessage)
118
+ * 1. Updates local state immediately (Message + ThreadMessage)
119
119
  * 2. Enqueues event to SQS for worker to sync to IMAP
120
120
  *
121
121
  * Following RFC 016 for message deletion and moving.
@@ -266,8 +266,8 @@ const toRecord = (
266
266
  * **Part-path uniqueness**: some IMAP servers (and the `message/rfc822`
267
267
  * inner-body convention) return child nodes with an empty `part` field.
268
268
  * Assigning ROOT_PART_PATH to every such node would produce duplicate keys
269
- * and cause a DynamoDB "multiple operations on one item" error in
270
- * `upsertBodyParts`. Non-root nodes without a `part` therefore receive a
269
+ * and make `upsertBodyParts` write the same body part twice. Non-root nodes
270
+ * without a `part` therefore receive a
271
271
  * synthetic path `<parentPath>.<siblingIndex>` that is stable across
272
272
  * repeated syncs of the same message.
273
273
  */
@@ -287,7 +287,7 @@ export const walkMimeStructure = (root: MimeNode): BodyPartRecord[] => {
287
287
  partPath = ROOT_PART_PATH;
288
288
  } else {
289
289
  // Non-root node without an IMAP part path — synthesise one so
290
- // the DynamoDB keys remain unique. This happens most commonly
290
+ // the body-part keys remain unique. This happens most commonly
291
291
  // for the body of a message/rfc822 attachment, whose inner
292
292
  // structure imapflow attaches as a childNode with part="".
293
293
  partPath = `${parentPath}.${siblingIndex}`;
@@ -2,9 +2,9 @@ import type { IUnitOfWork, UnitOfWorkRepositories } from "@remit/data-ports";
2
2
 
3
3
  /**
4
4
  * Runs the write set against fixed repositories with no surrounding
5
- * transaction. For backends (DynamoDB) that have no cross-entity transaction:
6
- * the writes are not atomic, matching that backend's own guarantees. The
7
- * Postgres path injects a real transactional unit of work instead.
5
+ * transaction: the writes are not atomic. For a backend that has no
6
+ * cross-entity transaction this matches its own guarantees; the SQLite path
7
+ * injects a real transactional unit of work instead.
8
8
  */
9
9
  export class PassThroughUnitOfWork implements IUnitOfWork {
10
10
  constructor(private repos: UnitOfWorkRepositories) {}