Search code examples
graphqlsubscriptiongraphql-jsgraphql-subscriptions

GraphQL subscriptions: Error on calling apolloClient.subscribe


I think I have the backend subscription setup correctly. I am using angular on the client side, when I try to call subscribe I got an error

passwordUpdatedSubscription = gql`
subscription passwordUpdated{passwordUpdated{name password}}
`;

// Apollo Subscription
var subscription = this.apollo.subscribe({
  query: this.passwordUpdatedSubscription
});

subscription.subscribe(
  {
    next(data) {
      console.log(data);
    },
    error(err) { console.error('err', err); },
  }
);

And then this is the error appears in the console {"type":"subscription_fail","id":0,"payload":{"errors":[{"message":"Cannot read property 'subscribe' of undefined"}]}}

Maybe I am missing something on the backend? Do I need to define the setupFunctions in the SubscriptionManager?

This is my SubscriptionManager

const sub = require('graphql-subscriptions');
const pubSub = new sub.PubSub();
const manager = new sub.SubscriptionManager({
    schema,
    pubSub
});

This is my schema in graphQL

const graphql = require('graphql');

var schema = graphql.buildSchema(`
    type Subscription {
      passwordUpdated: User
    }
    type Mutation {
      setMessage(message: String): String,
      updateUserPassword(userName: String, password: String): User!
    }

    type Query {
      getMessage: String,
      getUsers: [User],
      findUsers(userName: String): [User]
    }

    type User {
        name: String,
        password: String
    }
`);

Solution

  • Yes you are missing the setup function. You could take a look at this links graphql subscription docu or example.

    Your subscription manager could look like this:

    const manager = new sub.SubscriptionManager({
      schema,
      pubSub,
    
      setupFunctions: {
        passwordUpdated: (options, args) => ({ // name of your graphQL subscription
          passwordUpdatedChannel: { // name of your pubsub publish-tag
            filter: () => {
              return true
            },
          },
        }),
      },
    });

    When you call the pubsub publish function you have to write it like this pubsub.publish("passwordUpdatedChannel").

    Sidenode: You might want to add the id of the user that has the password changed to the subscription. If you do that you can add it to the filter option, could look like this filter: (user) => {return user.id === args.userId}