Documentation
¶
Index ¶
- func GetAccountCapabilities[T any](acc Account, c Capability) (T, error)
- func GetCapabilities[T any](s Session, c Capability) (T, error)
- type Account
- type Authenticator
- type BearerTokenAuthenticator
- type Capability
- type Client
- type ClientOpt
- type DefaultSessionCache
- type Invocation
- type InvocationError
- type MethodResponse
- type Request
- type Resolver
- type Response
- type ResultReference
- type Session
- type SessionCache
- type SessionGetter
- type StaticResolver
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAccountCapabilities ¶
func GetAccountCapabilities[T any](acc Account, c Capability) (T, error)
GetAccountCapabilities decodes the account-level capability object for the given capability identifier from an Account. Account-level capabilities describe per-account constraints and permissions, which may differ from the server-level capabilities. Returns an error if the capability is not present or cannot be decoded.
func GetCapabilities ¶
func GetCapabilities[T any](s Session, c Capability) (T, error)
GetCapabilities decodes the server-level capability object for the given capability identifier from the Session. The type parameter T should match the expected shape of the capability object as defined by the relevant RFC. Returns an error if the capability is not present or cannot be decoded.
Example ¶
package main
import (
"encoding/json"
"fmt"
jmap "github.com/rhyselsmore/go-jmap"
)
func main() {
sess := jmap.Session{
Capabilities: map[jmap.Capability]json.RawMessage{
"urn:ietf:params:jmap:core": json.RawMessage(`{"maxSizeUpload":50000000}`),
},
}
type CoreCapability struct {
MaxSizeUpload int `json:"maxSizeUpload"`
}
cap, err := jmap.GetCapabilities[CoreCapability](sess, "urn:ietf:params:jmap:core")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(cap.MaxSizeUpload)
}
Output: 50000000
Types ¶
type Account ¶
type Account struct {
Name string `json:"name"`
IsPersonal bool `json:"isPersonal"`
IsReadOnly bool `json:"isReadOnly"`
AccountCapabilities map[Capability]json.RawMessage `json:"accountCapabilities"`
}
Account represents a single JMAP account.
type Authenticator ¶
type Authenticator interface {
// Authenticate mutates req to add authentication credentials.
Authenticate(req *http.Request) error
}
Authenticator signs outgoing HTTP requests, e.g. by adding an Authorization header. Implement this interface to support custom authentication schemes.
type BearerTokenAuthenticator ¶
type BearerTokenAuthenticator struct {
// contains filtered or unexported fields
}
BearerTokenAuthenticator implements Authenticator using a static Bearer token. Use NewBearerTokenAuthenticator or WithBearerTokenAuthentication to construct one.
func NewBearerTokenAuthenticator ¶
func NewBearerTokenAuthenticator(token string) (*BearerTokenAuthenticator, error)
NewBearerTokenAuthenticator returns a BearerTokenAuthenticator for the given token. Returns an error if the token is empty or whitespace-only.
Example ¶
package main
import (
"fmt"
jmap "github.com/rhyselsmore/go-jmap"
)
func main() {
authn, err := jmap.NewBearerTokenAuthenticator("my-token")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(authn != nil)
}
Output: true
func (*BearerTokenAuthenticator) Authenticate ¶
func (b *BearerTokenAuthenticator) Authenticate(req *http.Request) error
type Capability ¶
type Capability string
Capability is a JMAP capability identifier, typically a URN such as "urn:ietf:params:jmap:core" or "urn:ietf:params:jmap:mail". Capabilities are used as keys in the Session and Account objects to advertise server support and constraints, and are passed in the "using" field of requests.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a JMAP client. Use NewClient to construct one.
func NewClient ¶
NewClient constructs a Client by applying the given options and then validating that all required fields (resolver, authenticator) are set.
type ClientOpt ¶
ClientOpt is a functional option applied to a Client during construction.
func WithAuthenticator ¶
func WithAuthenticator(authn Authenticator) ClientOpt
WithAuthenticator sets the Authenticator used to sign every outgoing request. This option is required; NewClient will return an error if it is not provided.
func WithBearerTokenAuthentication ¶
WithBearerTokenAuthentication is a convenience ClientOpt that creates a BearerTokenAuthenticator from the given token and sets it on the client.
func WithHTTPClient ¶
WithHTTPClient configures the Client to use the provided *http.Client instead of the default. The client is shallow-cloned to avoid mutating the caller's value.
func WithStaticResolver ¶
WithStaticResolver is a ClientOpt that configures the client to use a StaticResolver with the given HTTPS host URL.
type DefaultSessionCache ¶
type DefaultSessionCache struct {
// contains filtered or unexported fields
}
DefaultSessionCache is an in-memory SessionCache that refreshes the Session after a configurable TTL. It is safe for concurrent use.
func NewDefaultSessionCache ¶
func NewDefaultSessionCache(ttl time.Duration) *DefaultSessionCache
NewDefaultSessionCache returns a DefaultSessionCache that caches the Session for the given TTL duration.
func (*DefaultSessionCache) Get ¶
func (c *DefaultSessionCache) Get(ctx context.Context, fn SessionGetter) (Session, error)
Get returns the cached Session if it is still within the TTL, otherwise calls fn to fetch a fresh one and stores it. Uses a double-checked lock to avoid redundant fetches under concurrent access.
func (*DefaultSessionCache) Invalidate ¶
func (c *DefaultSessionCache) Invalidate(_ context.Context) error
Invalidate clears the cached Session so the next call to Get fetches a fresh one from the server.
type Invocation ¶
type Invocation interface {
// Name returns the JMAP method name, e.g. "Mailbox/query".
Name() string
// ID returns the client-specified call id (the 3rd element in the array).
// If it returns "", the request will generate one automatically.
ID() string
// DecodeResponse decodes the raw JSON response into the invocation's
// response type. The provided json.RawMessage is safe to mutate.
DecodeResponse(b json.RawMessage) error
}
Invocation represents a single JMAP method invocation in a request.
type InvocationError ¶
type InvocationError struct {
CallID string // the call ID of the failed invocation
Type string `json:"type"`
Detail string `json:"description,omitempty"`
}
InvocationError represents a server-side error returned for a single JMAP method invocation.
func (*InvocationError) Error ¶
func (e *InvocationError) Error() string
type MethodResponse ¶
type MethodResponse struct {
Name string // e.g. "Mailbox/get"
Args json.RawMessage // raw JSON object of the method's result
ID string // clientCallId, e.g. "c1"
}
MethodResponse represents a single JMAP method response triple: [ "Method/name", {args}, "clientCallId" ]
type Request ¶
type Request struct {
Using []Capability
MethodCalls []Invocation
// contains filtered or unexported fields
}
Request is the top-level JMAP request envelope sent to the server.
func NewRequest ¶
func NewRequest(using ...Capability) *Request
NewRequest creates a new request with the given capabilities.
Example ¶
package main
import (
"encoding/json"
"fmt"
jmap "github.com/rhyselsmore/go-jmap"
)
func main() {
req := jmap.NewRequest("urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail")
data, err := json.Marshal(req)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(string(data))
}
Output: {"using":["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"],"methodCalls":[]}
func (*Request) Add ¶
func (r *Request) Add(inv Invocation)
Add appends a method call to the request and assigns a unique call ID.
func (*Request) MarshalJSON ¶
MarshalJSON converts the request into the JMAP wire format:
{
"using": [...],
"methodCalls": [
["Mailbox/query", {...}, "c1"],
...
]
}
type Resolver ¶
Resolver resolves the JMAP session URL for a given server. Implementations may perform DNS lookups, SRV record queries, or simply return a statically configured URL.
type Response ¶
type Response struct {
MethodResponses []MethodResponse `json:"methodResponses"`
SessionState string `json:"sessionState"`
}
Response is the top-level JMAP response envelope.
func (*Response) UnmarshalJSON ¶
UnmarshalJSON implements custom decoding for the JMAP response envelope.
type ResultReference ¶
type ResultReference struct {
// ResultOf is the call ID of the previous method invocation whose
// result is being referenced.
ResultOf string `json:"resultOf"`
// Name is the method name of the previous invocation, e.g. "Mailbox/query".
// The server uses this to verify the reference points to the expected method.
Name string `json:"name"`
// Path is a JSON Pointer (RFC 6901) into the result object, identifying
// the value to extract. For example, "/ids/*" references the ids array
// from a /query response.
Path string `json:"path"`
}
ResultReference is a back-reference to the result of a previous method call within the same JMAP request, as defined in RFC 8620 Section 3.7. It allows the output of one invocation to be used as input to another, enabling dependent calls to be batched in a single round trip.
func Ref ¶
func Ref(inv Invocation, path string) *ResultReference
Ref creates a ResultReference from an existing Invocation, deriving the call ID and method name automatically. The path is a JSON Pointer into the referenced invocation's response.
Example ¶
package main
import (
"encoding/json"
"fmt"
jmap "github.com/rhyselsmore/go-jmap"
)
func main() {
// Ref creates a back-reference to use the output of one method call
// as input to another within the same request.
inv := &exampleInvocation{name: "Mailbox/query", id: "c1"}
ref := jmap.Ref(inv, "/ids/*")
fmt.Println(ref.ResultOf, ref.Name, ref.Path)
}
// exampleInvocation implements jmap.Invocation for examples.
type exampleInvocation struct {
name string
id string
}
func (e *exampleInvocation) Name() string { return e.name }
func (e *exampleInvocation) ID() string { return e.id }
func (e *exampleInvocation) DecodeResponse(_ json.RawMessage) error { return nil }
Output: c1 Mailbox/query /ids/*
type Session ¶
type Session struct {
// Capabilities advertises the capabilities the server supports,
// keyed by capability URI (e.g., "urn:ietf:params:jmap:core").
Capabilities map[Capability]json.RawMessage `json:"capabilities"`
// Accounts lists accounts the user has access to, keyed by account ID.
Accounts map[string]Account `json:"accounts"`
// PrimaryAccounts maps each capability to the default account ID
// for that capability.
PrimaryAccounts map[Capability]string `json:"primaryAccounts"`
// Username is the user’s primary identifier for this session.
Username string `json:"username"`
// APIUrl is the endpoint used for all JMAP method calls (POST).
APIURL string `json:"apiUrl"`
// DownloadURL is a template for downloading blobs.
// Replace {accountId} and {blobId}.
DownloadURL string `json:"downloadUrl"`
// UploadURL is a template for uploading blobs.
// Replace {accountId} and {blobId}.
UploadURL string `json:"uploadUrl"`
// EventSourceURL is the long-poll URL for push changes.
EventSourceURL string `json:"eventSourceUrl"`
// State is a string used to detect when the session object changes.
State string `json:"state"`
// Extensions can contain any unrecognized or server-specific fields.
Extensions map[string]any `json:"-"`
// contains filtered or unexported fields
}
Session represents the JMAP Session object defined in RFC 8620 §2.
type SessionCache ¶
type SessionCache interface {
// Get returns a cached Session, calling fn to fetch a fresh one if needed.
Get(ctx context.Context, fn SessionGetter) (Session, error)
// Invalidate discards the cached Session, forcing the next Get to refresh.
Invalidate(ctx context.Context) error
}
SessionCache manages caching of the JMAP Session object. Implement this interface to provide custom caching strategies (e.g. Redis, per-tenant).
type SessionGetter ¶
SessionGetter is a function that fetches a fresh Session from the server. It is passed to [SessionCache.Get] and called only when the cache is empty or expired.
type StaticResolver ¶
type StaticResolver struct {
// contains filtered or unexported fields
}
StaticResolver is a Resolver that returns a fixed JMAP session URL. It performs no network lookups; the URL is fully determined at construction time.
func NewStaticResolver ¶
func NewStaticResolver(raw string) (*StaticResolver, error)
NewStaticResolver creates a Resolver that always returns the JMAP well-known URL for the given host. The input must be an HTTPS URL containing only a scheme and host (with optional port). Paths, query parameters, and fragments are not permitted.
Example:
r, err := NewStaticResolver("https://api.fastmail.com")
Example ¶
package main
import (
"fmt"
jmap "github.com/rhyselsmore/go-jmap"
)
func main() {
r, err := jmap.NewStaticResolver("https://api.fastmail.com")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(r != nil)
}
Output: true