GraphQL subscriptions is a simple npm package that lets you wire up GraphQL with a pubsub system (like Redis) to implement subscriptions in GraphQL. You can use it with any GraphQL client and server (not only Apollo).
npm install graphql-subscriptions
This package should be used with a network transport, for example subscriptions-transport-ws.
The package exports PubSub
and SubscriptionManager
.
PubSub
is a simple pubsub implementation and is recommended only for use in development. It can be easily replaced with some other implementations of PubSubEngine interface. There are a couple of them out there:
- Use Redis with https://github.com/davidyaha/graphql-redis-subscriptions
- Use MQTT enabled broker with https://github.com/davidyaha/graphql-mqtt-subscriptions
- Use RabbitMQ with https://github.com/cdmbase/graphql-rabbitmq-subscriptions
- Add your implementation...
You will then call pubsub.publish('channelName', data)
to publish data
to the channelName
channel. This might happen inside a mutation resolver, for example.
Create a new instance of SubscriptionManager and pass in your schema
and pubsub
instance.
The setupFunctions
property is used to map subscription names (from your schema) to pubsub channel names. You can also provide filter functions to, for example, filter channel events based on query variables and the properties of the object published to the channel.
Note: Typically, your
SubscriptionManager
will be passed to a network transport like https://github.com/apollographql/subscriptions-transport-ws.
This example only demonstrates the
graphql-subscriptions
package. Take a look at this article for a more in-depth look at using GraphQL subscriptions.
import { PubSub, SubscriptionManager } from 'graphql-subscriptions';
import schema from './schema';
const pubsub = new PubSub();
const subscriptionManager = new SubscriptionManager({
schema,
pubsub,
// In this example we map the "commentAdded" subscription to the "newComments" channel.
// The subscription is then called each time a new comment is posted where the
// comment's `repoFullName` matches the `repoName` provided by the query.
setupFunctions: {
commentAdded: (options, args) => ({
newComments: {
filter: comment => comment.repoFullName === args.repoName,
},
}),
},
});
// Start a subscription. In normal usage you would do this client-side using something like
// subscriptions-transport-ws.
subscriptionManager.subscribe({
query: `
subscription newComments($repoName: String!){
commentAdded(repoName: $repoName) { # <-- this is the subscription name
id
content
createdBy {
username
}
}
}
`,
variables: {
repoName: 'apollostack/GitHunt-API',
},
context: {},
callback: (err, data) => console.log(data),
});
// Publish a comment to the "newComments" channel, potentially triggering a call to a matching
// subscription. For example, pubsub.publish() might be triggered inside a "createComment" mutation,
// after the comment has been created and added to the database.
pubsub.publish('newComments', {
id: 123,
content: 'Hello world!',
repoFullName: 'apollostack/GitHunt-API',
postedBy: 'helfer',
});
// the query will run, and the callback will print
// {
// data: {
// commentAdded: {
// id: 123,
// content: 'Test',
// createdBy: {
// username: 'helfer',
// }
// }
// }
// }