1

I have the following subscription query that works fine:

subscription{
  streamShipmentOrder{
    id
  }
}

But the following sends an "Cannot read property 'ShipmentOrder' of undefined" error

subscription{
  streamShipmentOrder{
    id
    logs{
      comment
    }
  }
}

Here is my ShipmentOrder type definition, I'm using sequelize to talk to the database

const ShipmentOrderType = new GraphQLObjectType({
    name: 'ShipmentOrder',
    fields: () => ({
       id: { type: GraphQLID },
       logs: {
          type: new GraphQLList(LogType),
          resolve: async (parent, args, { models }, info) => {
             return await models.ShipmentOrder.findOne({
                where: { id: parent.id },
                include: [{ model: models.Log }],
             }).then((data) => data.logs);
          }
       },
    }

And here is the Subscription definition

const ShipmentOrderSubscription = new GraphQLObjectType({
   name: 'Subscription',
   fields: () => ({
      streamShipmentOrder: {
         type: ShipmentOrderType,
         resolve: (payload) => payload.shipmentOrderData,
         subscribe: () =>
            socket.asyncIterator([
               SHIPMENT_ORDER_CREATED,
               SHIPMENT_ORDER_UPDATED,
               SHIPMENT_ORDER_DELETED
            ]),
      },
   }),
});

And the mutation that fires the subscription, (also the mutation works fine when asking for nested results)

const ShipmentOrderMutation = new GraphQLObjectType({
    name: 'Mutation',
    fields: () => ({
        createShipmentOrder: {
            type: ShipmentOrderType,
            args: {...},
            resolve: async (parent, args, { models }, info) => {

                // create shipmentOrder
                return await models.ShipmentOrder.create({...})
                    .then(async (createdShipmentOrder) => {

                    // create log and relate to created shipmentOrder
                    await models.Log.create({...});

                    // get created shipmentOrder with its logs
                    return await models.ShipmentOrder.findOne({
                        where: { id: createdShipmentOrder.id },
                        include: [{ model: models.Log }],
                    }).then((foundShipmentOrder) => {

                        // updates streams
                        socket.publish(SHIPMENT_ORDER_CREATED, {
                            shipmentOrderData: foundShipmentOrder,
                        });
                        return foundShipmentOrder;

                    });
                }
            }
        }
    })
});

What could I be missing?

  • Presumably, `models` is undefined inside the resolver for the `logs` field. How are you importing `models` inside that file? How is that object exported? Are you using the "associate" pattern outlined here (https://github.com/sequelize/express-example) to prevent cyclic dependencies? – Daniel Rearden Nov 25 '18 at 13:36
  • Yes @DanielRearden, associations work on every other query and mutation, also every subscription when asking only for the main type works too, it crashes only when asking for other "sub-properties" or relations on the graphql response object in a subscription, like in this problems case. – Otoniel Guajardo Nov 25 '18 at 18:03
  • @DanielRearden you where right! **Log** resolver context contains the **model** object when calling query and mutation but empty when calling subscription!! I'm still figuring out why... – Otoniel Guajardo Nov 25 '18 at 23:28

1 Answers1

0

As @DanielRearden pointed me out, context was empty when calling the subscription, and that messed up my relations, this because context is handled differently on query/mutations and subscriptions.

So what fixed it was adding my models object to the onConnect property of the subscriptions option in the ApolloServer, passing the same objects I was already passing to my context option

const server = new ApolloServer({
    schema,
    subscriptions: {
        onConnect: () => ({models}),
    },
    context: () => ({models})
}