@bobfrankston/mailx-sync
v0.1.10
Published
Platform-agnostic mail provider implementations + sync orchestration. Single source of truth for Gmail/IMAP/Outlook protocol code, consumed by both desktop (Node) and Android (WebView) — eliminates the parallel mailx-imap/mailx-store-web Gmail providers t
Maintainers
Readme
@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 servicemailx-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 viaTransportFactory—NodeTcpTransporton desktop,BridgeTcpTransporton Android).
How to instantiate
Desktop (Node service):
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):
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.tsre-exportsGmailApiProvider.mailx-imap/providers/types.tsre-exports the type interfaces.mailx-imap/providers/outlook-api.tsre-exportsOutlookApiProvider.mailx-store-web/gmail-api-web.tsre-exportsGmailApiProvider as GmailApiWebProvider.mailx-store-web/imap-web-provider.tsre-exportsImapProvider as ImapWebProvider.mailx-store-web/provider-types.tsre-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 tosync.tsconsuming theSyncStorage/SyncBodyStoreinterfaces. 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
