On this page

Live Queries

GraphQL Mesh v0 documentation (superseded by v1): Use GraphQL Mesh Live Queries to update GraphQL operation results automatically. Learn how to configure the Live Query plugin with examples and a code sandbox demo.

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.

.meshrc.yaml
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;

.meshrc.yaml
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:

.meshrc.yaml
invalidations:
  - field: Mutation.editTodo
    invalidate:
      - Query.todo(id:"{args.id}")

Polling Based Invalidation

You can also invalidate queries in a polling interval by specifying the schema coordinate of the query to be polled.

.meshrc.yaml
plugins:
  - liveQuery:
      invalidations:
        - pollingInterval: 10000 # Polling interval in milliseconds
          invalidate:
            - Query.products

Programmatic Usage

liveQueryStore is available in GraphQL Context, so you can access it in resolvers composition functions that wrap existing resolvers or additional resolvers;

See Resolvers Composition

.meshrc.yaml
transforms:
  - resolversComposition:
      - resolver: Mutation.editTodo
        composer: invalidate-todo#invalidateTodo

And in this code file;

invalidate-todo.ts
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

  • invalidations (type: Array of Object) - Invalidate a query or queries when a specific operation is done without an error:
    • field (type: String) - Path to the operation that could effect it. In a form: Mutation.something. Note that wildcard is not supported in this field.
    • pollingInterval (type: Int) - Polling interval in milliseconds
    • invalidate (type: Array of String, required)
  • resourceIdentifier (type: String) - Custom strategy for building resources identifiers By default resource identifiers are built by concatenating the Typename with the id separated by a color (User:1).

This may be useful if you are using a relay compliant schema and the Typename information is not required for building a unique topic.

Default: “{typename}:{id}”

  • includeIdentifierExtension (type: Boolean) - Whether the extensions should include a list of all resource identifiers for the latest operation result. Any of those can be used for invalidating and re-scheduling the operation execution.

This is mainly useful for discovering and learning what kind of topics a given query will subscribe to. The default value is true if DEBUG environment variable is set

  • idFieldName (type: String) - Identifier unique field

Default: “id”

  • indexBy (type: Array of Object) - Specify which fields should be indexed for specific invalidations.:
    • field (type: String, required)
    • args (type: Array of String, required)

CodeSandBox Example