Skip to content

Conversation

@i11v
Copy link
Owner

@i11v i11v commented Feb 11, 2026

Summary

This PR introduces a new Promise-based client wrapper (JMAPClientWrapper) that hides Effect-TS internals, making the library accessible to developers who don't want to work with Effect directly. The wrapper provides a familiar async/await API while maintaining full compatibility with the existing Effect-based architecture.

Key Changes

  • New wrapper.ts module: Implements JMAPClientWrapper interface with three namespaces:

    • MailboxNamespace: Promise-based mailbox operations (get, set, query, create, update, destroy, etc.)
    • EmailNamespace: Promise-based email operations (get, set, query, search, mark read, flag, move, etc.)
    • SubmissionNamespace: Promise-based email submission/sending operations
  • Three factory functions for creating the wrapper:

    • createJMAPClient(sessionUrl, bearerToken): Simple creation with default config
    • createJMAPClientWithConfig(config): Creation with custom configuration
    • createJMAPClientFromLayer(layer): Advanced usage with pre-built Effect layers
  • Auto-discovered account ID: The wrapper automatically discovers and exposes the primary account ID from the JMAP session, allowing convenience methods to use it as a default

  • Low-level batch API: Exposes batch() method for direct JMAP batch calls when needed

  • Resource management: Includes dispose() method to clean up the underlying Effect runtime

  • Comprehensive test suite: Added client-wrapper.test.ts with tests for creation, mailbox operations, email operations, and resource disposal

  • Updated exports: Modified src/client/index.ts to export the new wrapper types and functions, and renamed existing layer factories from createJMAPClientcreateJMAPClientLayer to avoid naming conflicts

  • Updated documentation: Enhanced README with Promise-based quick start example and reorganized Effect-based usage into a separate section

Implementation Details

  • The wrapper uses ManagedRuntime.make() to create a single Effect runtime instance that persists across all method calls
  • All methods are wrapped in Effect.gen() generators and executed via runtime.runPromise()
  • Optional accountId parameters on convenience methods default to the auto-discovered primary account ID
  • Error handling preserves the original TaggedError types from the Effect-based services
  • The wrapper maintains full type safety through TypeScript's Schema.Schema.Type utility for inferring types from Effect schemas

https://claude.ai/code/session_0152ZUp5oDUjuP7L1XevVMTr

Add a high-level client factory that hides Effect internals behind
a Promise-based API. Consumers can now use `await createJMAPClient(url, token)`
to get a client with `client.mailbox.getAll()`, `client.email.query()`, etc.

- Auto-discovers primary accountId from session
- Validates credentials on creation (async factory)
- Namespaced API: mailbox, email, submission
- ManagedRuntime for efficient layer caching
- dispose() for cleanup
- Existing Effect-based API unchanged
- Renamed createJMAPClient (layer factory) to createJMAPClientLayer

https://claude.ai/code/session_0152ZUp5oDUjuP7L1XevVMTr
@github-actions
Copy link

JMAP Spec Coverage

effect-jmap@0.8.0 coverage:spec /home/runner/work/effect-jmap/effect-jmap
tsx scripts/spec-coverage.ts --markdown

Overall: 15/31 methods (48.4%)

Blob (0/4)

Method Status
copy
get
lookup
upload

Core (0/1)

Method Status
echo

Email (6/8)

Method Status
get
set
query
queryChanges
changes
copy
import
parse

EmailSubmission (5/5)

Method Status
get
set
query
queryChanges
changes

Identity (0/3)

Method Status
get
set
changes

Mailbox (4/5)

Method Status
get
set
query
queryChanges
changes

SearchSnippet (0/1)

Method Status
get

Thread (0/2)

Method Status
get
changes

VacationResponse (0/2)

Method Status
get
set

@github-actions
Copy link

github-actions bot commented Feb 11, 2026

Preview Package Published

pnpm add effect-jmap@0.0.0-pr.18.c9c68c9
# or
pnpm add effect-jmap@pr-18

Published from commit c9c68c9

… calls

Replace verbose generator pattern with pipe-friendly flatMap for
two-line service calls in the wrapper (yield service, yield method).

https://claude.ai/code/session_0152ZUp5oDUjuP7L1XevVMTr
@github-actions
Copy link

JMAP Spec Coverage

effect-jmap@0.8.0 coverage:spec /home/runner/work/effect-jmap/effect-jmap
tsx scripts/spec-coverage.ts --markdown

Overall: 15/31 methods (48.4%)

Blob (0/4)

Method Status
copy
get
lookup
upload

Core (0/1)

Method Status
echo

Email (6/8)

Method Status
get
set
query
queryChanges
changes
copy
import
parse

EmailSubmission (5/5)

Method Status
get
set
query
queryChanges
changes

Identity (0/3)

Method Status
get
set
changes

Mailbox (4/5)

Method Status
get
set
query
queryChanges
changes

SearchSnippet (0/1)

Method Status
get

Thread (0/2)

Method Status
get
changes

VacationResponse (0/2)

Method Status
get
set

@github-actions
Copy link

JMAP Spec Coverage

effect-jmap@0.8.0 coverage:spec /home/runner/work/effect-jmap/effect-jmap
tsx scripts/spec-coverage.ts --markdown

Overall: 15/31 methods (48.4%)

Blob (0/4)

Method Status
copy
get
lookup
upload

Core (0/1)

Method Status
echo

Email (6/8)

Method Status
get
set
query
queryChanges
changes
copy
import
parse

EmailSubmission (5/5)

Method Status
get
set
query
queryChanges
changes

Identity (0/3)

Method Status
get
set
changes

Mailbox (4/5)

Method Status
get
set
query
queryChanges
changes

SearchSnippet (0/1)

Method Status
get

Thread (0/2)

Method Status
get
changes

VacationResponse (0/2)

Method Status
get
set

Add `initialSession` option to JMAPClientConfig and `session` option to
createJMAPClient() so consumers can pass a cached session, skipping the
initial HTTP round-trip to the session endpoint.

https://claude.ai/code/session_0152ZUp5oDUjuP7L1XevVMTr
@github-actions
Copy link

JMAP Spec Coverage

effect-jmap@0.8.0 coverage:spec /home/runner/work/effect-jmap/effect-jmap
tsx scripts/spec-coverage.ts --markdown

Overall: 15/31 methods (48.4%)

Blob (0/4)

Method Status
copy
get
lookup
upload

Core (0/1)

Method Status
echo

Email (6/8)

Method Status
get
set
query
queryChanges
changes
copy
import
parse

EmailSubmission (5/5)

Method Status
get
set
query
queryChanges
changes

Identity (0/3)

Method Status
get
set
changes

Mailbox (4/5)

Method Status
get
set
query
queryChanges
changes

SearchSnippet (0/1)

Method Status
get

Thread (0/2)

Method Status
get
changes

VacationResponse (0/2)

Method Status
get
set

@i11v i11v changed the title Add Promise-based JMAP client wrapper for simplified API usage feat: Add Promise-based JMAP client wrapper for simplified API usage Feb 11, 2026
@i11v i11v merged commit 76ae8d0 into main Feb 11, 2026
9 checks passed
@i11v i11v deleted the claude/simplify-fastmail-layers-yrizy branch February 11, 2026 20:21
effect-jmap-release bot pushed a commit that referenced this pull request Feb 11, 2026
# [0.9.0](v0.8.0...v0.9.0) (2026-02-11)

### Features

* Add Promise-based JMAP client wrapper (createJMAPClient) ([#18](#18)) ([76ae8d0](76ae8d0)), closes [hi#level](https://github.com/hi/issues/level)
@effect-jmap-release
Copy link

🎉 This PR is included in version 0.9.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants