@envelop/live-query
v7.0.0
Published
The easiest way of adding live queries to your GraphQL server!
Downloads
29,101
Readme
@envelop/live-query
The easiest way of adding live queries to your GraphQL server!
Push new data to your clients automatically once the data selected by a GraphQL operation becomes
stale by annotating your query operation with the @live
directive.
query UserProfile @live {
me {
id
login
bio
}
}
The invalidation mechanism is based on GraphQL ID fields and schema coordinates. Once a query operation has been invalidated, the query is re-executed and the result is pushed to the client.
Installation
yarn add @envelop/live-query @n1ru4l/in-memory-live-query-store
Usage Example
makeExecutableSchema
from graphql-tools
import { execute, parse, specifiedRules, subscribe, validate } from 'graphql'
import { envelop, useEngine, useExtendContext, useSchema } from '@envelop/core'
import { useLiveQuery } from '@envelop/live-query'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { InMemoryLiveQueryStore } from '@n1ru4l/in-memory-live-query-store'
const schema = makeExecutableSchema({
typeDefs: [
/* GraphQL */ `
type Query {
greetings: [String!]
}
`,
GraphQLLiveDirectiveSDL
],
resolvers: {
Query: {
greetings: (_, __, context) => context.greetings
}
}
})
const liveQueryStore = new InMemoryLiveQueryStore()
const greetings = ['Hello', 'Hi', 'Ay', 'Sup']
// Shuffle greetings and invalidate queries selecting Query.greetings every second.
setInterval(() => {
const firstElement = greetings.pop()
greetings.unshift(firstElement)
liveQueryStore.invalidate('Query.greetings')
}, 1000)
const getEnveloped = envelop({
plugins: [
useEngine({ parse, validate, specifiedRules, execute, subscribe }),
useSchema(schema),
useLiveQuery({ liveQueryStore }),
useExtendContext(() => ({ greetings }))
/* other plugins */
]
})
GraphQLSchema
from graphql
You need to pass the GraphQLLiveDirective
to the list of directives:
import { GraphQLSchema } from 'graphql'
import { GraphQLLiveDirective } from '@envelop/live-query'
const schema = new GraphQLSchema({
directives: [...specifiedDirectives, GraphQLLiveDirective]
})
Applying a patch middleware
By using a patch middleware you can significantly reduce the size of the GraphQL execution result
payload that is sent over the wire from the server to the client. We recommend using the
@n1ru4l/graphql-live-query-patch-jsondiffpatch
patch generator.
You can learn more about it here.
yarn add @n1ru4l/graphql-live-query-patch-jsondiffpatch
import { applyLiveQueryJSONDiffPatchGenerator } from '@n1ru4l/graphql-live-query-patch-jsondiffpatch'
import { InMemoryLiveQueryStore } from '@n1ru4l/in-memory-live-query-store'
const liveQueryStore = new InMemoryLiveQueryStore()
const plugin = useLiveQuery({
liveQueryStore,
applyLiveQueryPatchGenerator: applyLiveQueryJSONDiffPatchGenerator
})
Further information
This plugin requires you to use a graphql transports that supports usage of the @defer
and
@stream
directives, as it is built upon the same concepts (return an AsyncIterable
from
execute
).
The following transports have been successfully tested:
| Package | Transport | Version | Downloads |
| -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| @n1ru4l/socket-io-graphql-server
| GraphQL over Socket.io (WebSocket/HTTP Long Polling) | | |
| graphql-helix
| GraphQL over HTTP (IncrementalDelivery/SSE) | | |
| graphql-ws
| GraphQL over WebSocket (WebSocket) | | |
| graphql-sse
| GraphQL over Server-Sent Events (SSE) | | |
For more details check out the live query repository or the introduction blog post.