Live Queries
GraphQL Live Query implementation from Laurin Quast can be used in GraphQL Mesh with a few additions in the configuration.
npm i @graphql-mesh/plugin-live-query
Basic Usage
You have a Query
root field that returns all Todo
entities from your data source like below.
query getTodos {
todos {
id
content
}
}
And you want to update this operation result automatically without manual refresh when
Mutation.addTodo
is called.
You only need to add the following to your existing configuration.
additionalTypeDefs: |
directive @live on QUERY
plugins:
- liveQuery:
invalidations:
- field: Mutation.addTodo
invalidate:
- Query.todos
Then you can send a live query with @live
directive.
query getTodos @live {
todos {
id
content
}
}
This will start a real-time connection between the server and your client. The response of todos
will get updated whenever addTodo
is called.
ID Based Invalidation
Let's say you have the following query that returns a specific Todo
entity based on id
field;
query getTodo($id: ID!) {
todo(id: $id) {
id
content
}
}
If you update this entity with editTodo
mutation field on your backend, then you want to
invalidate this entity specifically instead of validating all todo
queries;
invalidations:
- field: Mutation.editTodo
invalidate:
- Todo:{args.id}
In a case where the field resolver resolves null but might resolve to an object type later, e.g., because the visibility got update the field that uses a specific id argument can be invalidated in the following way:
invalidations:
- field: Mutation.editTodo
invalidate:
- Query.todo(id:"{args.id}")
Programmatic Usage
liveQueryStore
is available in GraphQL Context, so you can access it in resolvers composition
functions that wrap existing resolvers or additional resolvers;
transforms:
- resolversComposition:
- resolver: Mutation.editTodo
composer: invalidate-todo#invalidateTodo
And in this code file;
module.exports = {
invalidateTodo: next => async (root, args, context, info) => {
const result = await next(root, args, context, info)
context.liveQueryStore.invalidate(`Todo:${args.id}`)
return result
}
}
Config API Reference
ttl
(type:Float
) - Maximum age in ms. Defaults toInfinity
. Set it to 0 for disabling the global TTL.ttlPerCoordinate
(type:Array of Object
) - Overwrite the ttl for query operations whose selection contains a specific schema coordinate (e.g. Query.users). Useful if the selection of a specific field should reduce the TTL of the query operation.:coordinate
(type:String
, required)ttl
(type:Float
, required)
ignoredTypes
(type:Array of String
) - Skip caching of following the types.idFields
(type:Array of String
) - List of fields that are used to identify the entity.invalidateViaMutation
(type:Boolean
) - Whether the mutation execution result should be used for invalidating resources. Defaults totrue
includeExtensionMetadata
(type:Boolean
) - Include extension values that provide useful information, such as whether the cache was hit or which resources a mutation invalidated.sessionId
(type:String
) - Allows to cache responses based on the resolved session id. Return a unique value for each session. Creates a global session by default. Example;
sessionId: "{context.headers.userId}"
if
(type:String
) - Specify whether the cache should be used based on the context.
if: "context.headers.userId != null"
cacheKey
(type:String
) - Customize the behavior how the response cache key is computed from the documentString, variableValues, contextValue and sessionId. If the given string is interpolated as empty, default behavior is used. Example;
# Cache by specific value
cacheKey: "{variableValues.userId}"
# Cache by documentString
cacheKey: "{documentString}"
# Cache by operationName
cacheKey: "{operationName}"
# Cache by some header value
cacheKey: "{contextValue.headers.authorization}"
# Or combine two of each
cacheKey: "{contextValue.headers.authorization}-{operationName}"
shouldCacheResult
(type:String
) - Checks if the result should be cached.
shouldCacheResult: "result.errors.length > 0"
CodeSandBox Example
You can learn more about GraphQL Live Query in its documentation. You can check out our example that uses live queries