Search code examples
node.jsgraphqlgraphql-subscriptions

GraphQL Subscriptions - subscriptionsClient.subscribe is not a function


So, I'm trying create a basic GraphQL Subscription Server. Problem in request result in graphiql. It's - "subscriptionsClient.subscribe is not a function". I don't understand where's problem.

For GraphQL Subscription Server I have used: graphql-server-express, subscriptions-transport-ws, graphql-subscriptions

So, it's the task for you, GraphQL masters.

Code:

index.js

const { createServer } = require('http')
const app = require('express')();
const bodyParser = require('body-parser')
const { graphqlExpress, graphiqlExpress } = require('graphql-server-express')
const { SubscriptionServer } = require('subscriptions-transport-ws')
const { subscribe, execute } = require('graphql');
const schema = require('./schema');

app.use(bodyParser.json());
app.use('/graphql', new graphqlExpress({
  schema
}));
app.use('/graphiql', new graphiqlExpress({
  endpointURL: '/graphql',
  subscriptionsEndpoint: 'ws://localhost:4000/subscriptions'
}));

const server = createServer(app);

server.listen(4000, () => {
  console.log("Server is listening on port 4000!");

  subscriptionServer = SubscriptionServer.create(
    {
      schema,
      execute,
      subscribe,
      onConnect: () => console.log("Client connected!")
    }, {
      server,
      path: '/subscriptions'
    }
  );
});

schema.js

const {
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLNonNull,
  GraphQLList,
  GraphQLID,
  GraphQLString
} = require('graphql');
const { PubSub, withFilter } = require('graphql-subscriptions');
const socket = new PubSub();
const store = [];
const NameType = new GraphQLObjectType({
  name: "Name",
  fields: {
    id: { type: GraphQLID },
    name: { type: GraphQLString }
  }
});
const RootQuery = new GraphQLObjectType({
  name: "RootQuery",
  fields: {
    names: {
      type: new GraphQLList(NameType),
      resolve: () => store
    }
  }
});
const RootMutation = new GraphQLObjectType({
  name: "RootMutation",
  fields: {
    addName: {
      type: NameType,
      args: {
        name: { type: new GraphQLNonNull(GraphQLString) }
      },
      resolve(_, { name }) {
        let model = {
          id: store.length,
          name
        }
        socket.publish("names", model);
        store.push(model);
        return model;
      }
    }
  }
});
const RootSubscription = new GraphQLObjectType({
  name: "RootSubscription",
  fields: {
    names: {
      type: NameType,
      resolve() {
        console.log("IS RUNNING");
      },
      subscribe: withFilter(() => pubsub.asyncIterator("names"), (payload, variables) => {
        return payload.names.id === variables.relevantId;
      })
    }
  }
});
module.exports = new GraphQLSchema({
  query: RootQuery,
  mutation: RootMutation,
  subscription: RootSubscription
});

Solution

  • Ok, here's thing.

    I've created a fully responsive GraphQL Subscriptions Server using Apollo-Server. Just use apollo-server-express and apollo-server packages for this task. ApolloServer provides GraphQL Playground that is supports subscriptions. So it's easy to debug and use it on front-end.

    Good Luck!