Skip to content

Instantly share code, notes, and snippets.

@alloy

alloy/LiveQueryPolyfill.ts

Last active Jun 13, 2020
Embed
What would you like to do?
Rewrite GraphQL Live Query to subscription.
/**
* This is a Live Query polyfill, as graphql-js does not strictly have support for that. Instead, we leave it up to the
* client to recognize a Live Query is requested with the `@live` directive on a `query` operation and here we
* transform it into a `live` subscription instead.
*
* Consider a schema like the following:
*
* ```graphql
type Badge {
id: ID!
}
type Query {
current: Badge!
}
type Subscription {
live: Query!
}
* ```
*
* …and an incoming query like the following:
*
* ```graphql
query BadgeQuery @live {
current {
id
}
}
* ```
*
* This polyfill will then rewrite it to be:
*
* ```graphql
subscription BadgeQuery {
live {
current {
id
}
}
}
* ```
*/
function rewriteLiveQuery(ast: DocumentNode): { document: DocumentNode, live: boolean } {
let live = false;
const document = visit(ast, {
OperationDefinition: {
leave(operationNode) {
if (operationNode.operation === "query" && live) {
return {
...operationNode,
// Change the operation to be a subscription
operation: "subscription",
// Insert a `live` field selection in place of the existing selection set…
selectionSet: {
kind: "SelectionSet",
selections: [{
kind: "Field",
name: {
kind: "Name",
value: "live",
},
// …and add the existing selection set to the new `live` field selection.
selectionSet: operationNode.selectionSet,
}],
},
};
}
},
},
Directive(directiveNode) {
if (directiveNode.name.value === "live") {
live = true;
// Delete the `live` directive
// eslint-disable-next-line no-null/no-null
return null;
}
},
SelectionSet() {
// Ensure we don't find directives anywhere else in the query
return false;
},
});
return {
document,
live,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.