# @bobfrankston/mailx-sync

Platform-agnostic mail provider implementations + sync orchestration interfaces. Single source of truth for protocol code consumed by both desktop (Node service) and Android (WebView).

## Why this package exists

Before this extraction, mailx maintained **parallel implementations** of the same Gmail provider in two places:

- `mailx-imap/providers/gmail-api.ts` — used by the Node desktop service
- `mailx-store-web/gmail-api-web.ts` — used by the Android WebView

They drifted in practice. A 403-quota retry added to the desktop copy one day was missed in the web copy until users reported broken prefetch. Per `programming.md`'s **Economy of Mechanism** rule (the operational TS-spirit example), platform-forking the same protocol logic is a textbook violation: TypeScript's value is *one typed implementation imported everywhere it's needed*, not separate "Node" and "browser" copies of the same algorithm.

## What's in here

| Export | What it is |
|---|---|
| `MailProvider` (interface) | Protocol-agnostic provider contract — list folders, fetch messages, get UIDs, close. |
| `ProviderFolder`, `ProviderMessage`, `FetchOptions` | Shared data shapes used at provider boundaries. |
| `GmailApiProvider` | Gmail REST API. Bounded-concurrency batch fetch, 403-quota retry, exponential backoff. |
| `ImapProvider` | Generic IMAP via `iflow-direct`'s `CompatImapClient`. Auto-reconnect on broken pipe. |
| `OutlookApiProvider` | Microsoft Graph for Outlook.com / Office 365. Skeleton — needs Azure app reg for production. |
| `SyncStorage`, `SyncBodyStore`, `SyncEventSink` (interfaces) | What sync orchestration needs from the host platform's database / file store / event bus. Used to keep `sync.ts` (planned) platform-free. |
| `SyncFolder` | Storage-side folder shape. |

## Platform requirements

Pure TypeScript, no Node-specific imports. Runtime needs only:

- `globalThis.fetch` — Node 18+ and all browsers/WebViews.
- `atob`, `Uint8Array`, `TextDecoder` — universal.
- A TCP byte-stream transport for `ImapProvider` (caller injects via `TransportFactory` — `NodeTcpTransport` on desktop, `BridgeTcpTransport` on Android).

## How to instantiate

**Desktop (Node service):**

```ts
import { GmailApiProvider, ImapProvider } from "@bobfrankston/mailx-sync";
import { NodeTcpTransport } from "@bobfrankston/node-tcp-transport";

const gmail = new GmailApiProvider(() => getGmailToken());

const imap = new ImapProvider(
    { server: "imap.example.com", port: 993, username: "u", password: "p" },
    () => new NodeTcpTransport(),
);
```

**Android (WebView Worker or main):**

```ts
import { GmailApiProvider, ImapProvider } from "@bobfrankston/mailx-sync";
import { BridgeTcpTransport } from "@bobfrankston/tcp-transport";

const gmail = new GmailApiProvider(() => getGmailToken());

const imap = new ImapProvider(
    { server: "imap.example.com", port: 993, username: "u", password: "p" },
    () => new BridgeTcpTransport(),
);
```

Identical API. The only platform-specific bit is the transport factory, which the package consumer injects.

## Back-compat shims

The earlier per-platform files now exist as thin re-exports so older import paths keep compiling:

- `mailx-imap/providers/gmail-api.ts` re-exports `GmailApiProvider`.
- `mailx-imap/providers/types.ts` re-exports the type interfaces.
- `mailx-imap/providers/outlook-api.ts` re-exports `OutlookApiProvider`.
- `mailx-store-web/gmail-api-web.ts` re-exports `GmailApiProvider as GmailApiWebProvider`.
- `mailx-store-web/imap-web-provider.ts` re-exports `ImapProvider as ImapWebProvider`.
- `mailx-store-web/provider-types.ts` re-exports the type interfaces.

Don't extend these shims — extend `mailx-sync` itself.

## Future work (in mailx's TODO.md)

- Sync orchestration (`syncFolderViaApi`, `prefetchBodies`) extracted to `sync.ts` consuming the `SyncStorage`/`SyncBodyStore` interfaces. Eliminates the "android-bootstrap.ts has its own simpler syncFolder" duplication.
- Storage adapters in mailx-store and mailx-store-web that satisfy `SyncStorage`.
- Outbox claim logic shared (currently desktop-only).

## License

ISC
