aerogear / graphback

Graphback - Out of the box GraphQL server and client
https://graphback.dev
Apache License 2.0
409 stars 73 forks source link

Subscriptions not working in GraphiQL Playground with Fastify #2174

Open craicoverflow opened 4 years ago

craicoverflow commented 4 years ago

// TODO

In the fastify-mongo-server-ts template, subscriptions appear to not be working using the GraphiQL Playground:

{
  "errors": [
    {
      "message": "Cannot return null for non-nullable field Subscription.newNote.",
      "locations": [
        {
          "line": 31,
          "column": 3
        }
      ],
      "path": [
        "newNote"
      ]
    }
  ],
  "data": null
}

This may not be an issue with Graphback, but it also might be. As such let's have this issue to ensure this is resolved. The Fastify templates are turned off until then.

Once this is resolved please check that the templates work and enable them in the CLI:

https://github.com/aerogear/graphback/blob/57de51595b51b56e211753fcc7e63f2fe3a8afaa/packages/create-graphback/src/init/starterTemplates.ts#L80

https://github.com/aerogear/graphback/blob/57de51595b51b56e211753fcc7e63f2fe3a8afaa/packages/create-graphback/src/init/starterTemplates.ts#L51

machi1990 commented 4 years ago

Automatically generated comment to notify maintainers /cc @machi1990, @wtrocki

RinkiyaKeDad commented 3 years ago

Hey @craicoverflow! I'd like to help solve this issue.

but it also might be

To be sure that it is not a Graphback issue I wanted to look at the resolvers which get generated. I was looking for them and as far as I could understand they get generated here. But I still am not sure how to see the actually generated resolvers file. Can you please point me to it? Thanks.

craicoverflow commented 3 years ago

Hi @RinkiyaKeDad!

The resolvers are created in the SchemaCRUDPlugin

RinkiyaKeDad commented 3 years ago

Hi @craicoverflow! There were some Typescript types related errors in SchemaCRUDPlugin. For example when adding the create subscription resolver I was getting this error in the console:

Argument of type 'IUnionTypeResolver | IEnumTypeResolver | IInputObjectTypeResolver | IObjectTypeResolver<any, any, any> | IInterfaceTypeResolver<...>' is not assignable to parameter of type 'IObjectTypeResolver<any, any, any>'.
  Type 'IUnionTypeResolver' is not assignable to type 'IObjectTypeResolver<any, any, any>'.
    Type 'IUnionTypeResolver' is not assignable to type '{ [key: string]: IFieldResolver<any, any, any, any> | IFieldResolverOptions<any, any, any>; }'.

I am not entirely sure if this is responsible for subscriptions not working. Please let me know your views on this. Till then I'll try creating a Fastify server the same way as we did in the template and if that works I think it could confirm if the problem is with the way we created the template or not.

Thanks and happy holidays!

wtrocki commented 3 years ago

@RinkiyaKeDad Our resolvers work with Apollo format. Fastify (graphql-js) uses different format for subscription resolvers

https://www.apollographql.com/docs/apollo-server/data/subscriptions/

Typescript issues are just manifestation of this problem.

RinkiyaKeDad commented 3 years ago

@wtrocki but isn't the SchemaCRUDPlugin file independent of the template we use and so should not be showing the TypeScript errors?

If that is not the case can you point me to what I should look into inorder to solve this? I reckon changing the way the Graphback resolvers work for a this one particular case work would not be a good idea, right?

wtrocki commented 3 years ago

We do not need to change how resolvers work. Our template need to enable subscriptions and handle them.

Cannot return null for non-nullable field Subscription.newNote

We need to map resolver function definitions to be compatible. Graphback output resolvers: https://github.com/aerogear/graphback/blob/2f8bb076b524c062e00e1cf1494d9af495bf3f12/packages/graphback-codegen-schema/src/SchemaCRUDPlugin.ts#L652

Graphback outputs resolvers to user template, so it is up to template to make them work. Fastify template is not setting resolvers right way.

For more info see https://www.apollographql.com/docs/graphql-subscriptions/

wtrocki commented 3 years ago

If we take look on the code template expects function but receives object with subscribe method.

To prove that this is going to resolve issue you can do this in template

subscriptionObj[operation] = subscriptionObj[operation].subscribe
RinkiyaKeDad commented 3 years ago

Thanks for the detailed explanation @wtrocki. I understand what the problem is now.

I looked up on it a bit more and I think the problem is actually with mercurius and not fastify itself. I'm not sure yet but I think the fix could be simply specifying the resolvers here because like you pointed out

code template expects function but receives object

If you have a look at the plugin options mercurius provides, you'll see that the second one is the list is resolvers and that expects an object like you said before.

Please let me know if this is the way to proceed or if you have something else in mind.

We need to map resolver function definitions to be compatible

I searched regarding this too but couldn't figure out how to go ahead with it 😅

wtrocki commented 3 years ago

Surprisingly mercurius documents resolvers the same way as Graphback:

https://github.com/mercurius-js/mercurius/blob/master/docs/subscriptions.md

Eg:

 Subscription: {
    notificationAdded: {
      subscribe: async (root, args, { pubsub }) =>
        await pubsub.subscribe('NOTIFICATION_ADDED')
    }
  }
RinkiyaKeDad commented 3 years ago

Surprisingly mercurius documents resolvers the same way as Graphback

This would mean the solution I mentioned should work I guess. Will try it out and raise a PR.