@mattkrick/graphql-trebuchet-client
v2.2.1
Published
A graphql client to get your subscriptions through tough firewalls and unreliable mobile networks
Downloads
330
Maintainers
Readme
graphql-trebuchet-client
A graphql client to get your subscriptions through tough firewalls and unreliable mobile networks
Why?
GraphQL subscriptions are important. Some corporate firewalls block long-running requests like WebSockets. This gets through them, one way or another.
What's it do?
- This is just a GraphQL protocol layer, which sits on top of the connection layer
- Keeps track of your fetches & subscriptions
- Resubscribes when the connection is ended prematurely
- Supports multiple responses for the same fetch, allowing for partial resutls using e.g.
@defer
How's it different from other graphql client libs?
- This lib won't fail silently when WebSockets fail
- This lib has a pure separation of concerns between connectivity & GraphQL messages
- Other libs do too much so they can lock you into their monolithic trap (don't get got!)
- Supports enforced casual ordering
What's the protocol?
From the client:
- An operations MAY have an
id
string - If
id
is provided, the server MUST reply, else it MAY not (e.g. analytics mutation) - An operation has a
type
, andpayload
- The type MUST be
start
orstop
- a
start
payload MAY include aquery
param, or adocumentId
param (for persisted queries) - a
stop
operation MUST include theid
of the operation to unsubscribe from - The client MUST send a single operation (batching is left up to the transport)
From the server:
- An operation has an
id
,type
, andpayload
- The
id
MUST match theid
of the request - The
type
MUST bedata
,error
, orcomplete
- The payload MUST be a GraphQLResult (
{data, errors}
) - If the
type
isdata
, the client MUST callsink.next
- If the
type
iserror
, the client MUST callsink.error
with anError
instance - If the
type
iscomplete
, the client MUST callsink.next
iif a payload is present and callsink.complete
after
API
These are the methods you'll probably want to call.
fetch({query, cacheConfig, variables}, sink)
: Call this for all queries/mutationssubscribe({query, variables}, sink): Disposable
: Call this to start a subscription. Call the return value to stop it.close()
: Unsubscribe from everything and prevent a reconnect. Useful for logouts.
Example
import getTrebuchet, {SocketTrebuchet, SSETrebuchet} from '@mattkrick/trebuchet-client'
import GQLTrebuchetClient, {GQLHTTPClient} from '@mattkrick/graphql-trebuchet-client'
// you can use a plain old websocket here if you don't want to use trebuchet-client.
const trebuchet = await getTrebuchet(settings)
const transport = new GQLTrebuchetClient(trebuchet)
const myFetch = (query, variables) => {
// If 2 mutations with the same casualOrderingGroup get called in order A,B,
// then the server response for A is guaranteed to get dispatched before B
const cacheConfig = {metadata: {casualOrderingGroup: 'orderedStochasticMutations'}}
// note using a promise is easy to get started, but means you can't return multiple responses
return new Promise((resolve, reject) => {
return transport.fetch({query, cacheConfig, variables}, {
next(result): {
resolve(result)
},
error(error): {
reject(error)
},
complete(maybeResult): {
resolve(result)
}
})
})
transport.subscribe({query, variables}, subSink)