2

I'm working on learning the new Apollo pubsub code, using examples from GitHunt-API and GitHunt-React. When I call subscribe on the client, I'm getting the console log error:

"Cannot query field "createIM" on type "Subscription".

I've tried to follow the sample code very closely, but I'm missing something.

How can I correct this error?

CREATE_IM.JSX

class CreateIM extends React.Component {
[.....]
    subscribe(fromID, toID, updateCommentsQuery) {
        const SUBSCRIPTION_QUERY = gql`
          subscription IMAdded($fromID: String!, $toID: String!, $msgText: String!){
              createIM(fromID: $fromID, toID: $toID, msgText: $msgText){
                fromID
                toID
                msgText
  }
}
    `;
        this.subscriptionObserver = this.props.client.subscribe({
            query: SUBSCRIPTION_QUERY,
            variables: { fromID: this.fromID, toID: this.toID },
        }).subscribe({
            next(data) {
                debugger;
                const newComment = data.commentAdded;
                updateCommentsQuery((previousResult) => {
                    // if it's our own mutation, we might get the subscription result
                    // after the mutation result.
                    if (isDuplicateComment(newComment, previousResult.entry.comments)) {
                        return previousResult;
                    }
                    // update returns a new "immutable" list with the new comment
                    // added to the front.
                    return update(
                        previousResult,
                        {
                            entry: {
                                comments: {
                                    $unshift: [newComment],
                                },
                            },
                        }
                    );
                });
            },
            error(err) { debugger; console.error('err', err); }, //<== ERROR ON THIS LINE
        });
    }

SCHEMA

import Resolvers from '/imports/api/resolvers';
import Connectors from '/imports/api/db-connectors';
import { makeExecutableSchema } from 'graphql-tools';

const typeDefinitions = [`

type instant_message {
  id: Int
  fromID: String
  toID: String
  msgText: String
}
type Query {
  instant_message(fromID: String, toID: String, msgText: String): [instant_message]
}
type Mutation {
  createIM(
    fromID: String!
    toID: String!
    msgText: String!
  ): instant_message
}
type Subscription {
  # Subscription fires on every comment added
  IMAdded(fromID: String!, toID: String!, msgText: String!): instant_message
}

schema {
  query: Query,
  mutation: Mutation
  subscription: Subscription
}

`];


const executableSchema = makeExecutableSchema({
    typeDefs: typeDefinitions,
    resolvers: Resolvers,
    connectors: Connectors,
    logger: console,
});

export default executableSchema;

SUBSCRIPTIONS (SERVER CODE)

import { print } from 'graphql-tag/printer';
import { PubSub, SubscriptionManager } from 'graphql-subscriptions';
import schema from '/imports/api/schema';

const pubsub = new PubSub();
const subscriptionManager = new SubscriptionManager({
    schema,
    pubsub,
    setupFunctions: {
        IMAdded: (options, args) => ({
            IMAdded: comment => true, //not quite sure yet what validation needs to be here
        }),
    },
});

export { subscriptionManager, pubsub };

RESOLVERS

const resolvers = {
    Query: {
        instant_message(_, args) {
            var ret = connectors.IM.findAll({ where: args }).then((res) => res.map((item) => item.dataValues));
            return ret;
        }
    },
    Mutation: {
        createIM(root, args, context) {
            return Promise.resolve()
                .then(() => (
                    connectors.IM.create(args)
                ))
                .then(([args]) =>
                    connectors.IM.findAll({ where: args }).then((res) => res.map((item) => item.dataValues))
                )
                .then(comment => {
                    // publish subscription notification
                    pubsub.publish('IMAdded', comment);
                    return comment;
                });
        },
  },
    Subscription: {
        IMAdded(fromID, toID, msgText) {
            // the subscription payload is the comment.
            return msgText;
        },
    }

};
VikR
  • 4,818
  • 8
  • 51
  • 96

1 Answers1

1

You are selecting a mutation field inside your subscription. You have to use the subscription field instead. Just change the line in the query that has the mutation to use the subscription:

createIM(fromID: $fromID, toID: $toID, msgText: $msgText){

change it to this:

IMAdded(fromID: $fromID, toID: $toID){

If you set up your subscriptions correctly, then the IMAdded resolver will get the mutation result through the pubsub system, and you can select the subfields of instant_message directly on the subscription.

Also, notice i removed the msgText argument to IMAdded. It doesn't really make sense. The subscription arguments can be used to filter the messages, but the actual message will come in through the root value.

helfer
  • 7,042
  • 1
  • 20
  • 20
  • I want to make sure I follow what you are saying correctly. Should it be ``` subscribe(fromID, toID, updateCommentsQuery) { const SUBSCRIPTION_QUERY = gql` subscription IMAdded($fromID: String!, $toID: String!, $msgText: String!){ } } `;``` – VikR Oct 03 '16 at 22:35
  • I can think of a couple other variations that might be what you are advising. I want to make sure I get the right one as I am getting error messages with all the variations I can think of, and I want to make sure I get this part right so as to continue correctly. :) – VikR Oct 03 '16 at 22:37
  • I didn't read your code carefully enough. I've updated my answer to fix what I think the actual problem is. – helfer Oct 03 '16 at 22:46