Nexus: Subscription Example/Support?

Created on 8 Feb 2019  路  16Comments  路  Source: graphql-nexus/nexus

Are subscriptions currently supported and if so are there any examples?

typfeat

Most helpful comment

How is the status of this? I am really looking forward to use Subscriptions with nexus and nexus-prisma

All 16 comments

I'm also very interested in the subscription examples. Awesome work so far!

Subscriptions actually still need to be implemented.

Most of it should be as simple as following the patterns in objectType and adding a separate subscribe field & typings for that. I'll probably get around to it in the next week or two, but if anyone wants to dig into the library a bit and take a shot at it though, a PR would be welcome!

How is the status of this? I am really looking forward to use Subscriptions with nexus and nexus-prisma

@tgriesser is there anything we can help you with?

Started doing a little investigation into this. Can folks who use subscriptions clarify what their expectations might be for an API here? I've never used GraphQL subscriptions so I want to make sure I'm understanding the use case/how the types fit together. I think it might need to be a bit different than the normal patterns.

Proposed API:

export const newSubField = subscriptionField('someField', {
  type: SomeType,
  subscribe() {
    // ...
  },
  resolve() {
    // ...
  }
})

Open Questions:

  1. What is the signature of subscribe?
subscribe(root, args, ctx, info): AsyncIterator<T>

What is the type of the root here? Is it empty object, similar to Query/Mutation? Is root ever even useful here, or should we do something similar to https://github.com/taion/graphql-relay-subscription and just omit it: subscribe(args, ctx, info)?

Is ctx always guaranteed to be the same type as the one in normal query resolvers, or can/should it be different?

What is T in the above return, and where should it come from? Should the developer provide this as it works with other typings or can it be inferred?

  1. What is the signature of resolve?
resolve(root, args, ctx, info)

What is root here, is this the type T from the above subscribe?

Is it reasonable that we require a resolve always be provided alongside the subscribe, even if it's just an identity function resolve: root => root

I don't think this should take too much to add, just wanted to be clear on the api we're looking for here.

Also, another question: is the only time you'd ever use/implement subscribe on the root Subscription type?

Just opened #66

Started doing a little investigation into this. Can folks who use subscriptions clarify what their expectations might be for an API here? I've never used GraphQL subscriptions so I want to make sure I'm understanding the use case/how the types fit together. I think it might need to be a bit different than the normal patterns.

Proposed API:

export const newSubField = subscriptionField('someField', {
  type: SomeType,
  subscribe() {
    // ...
  },
  resolve() {
    // ...
  }
})

Open Questions:

  1. What is the signature of subscribe?
subscribe(root, args, ctx, info): AsyncIterator<T>

What is the type of the root here? Is it empty object, similar to Query/Mutation? Is root ever even useful here, or should we do something similar to https://github.com/taion/graphql-relay-subscription and just omit it: subscribe(args, ctx, info)?

Is ctx always guaranteed to be the same type as the one in normal query resolvers, or can/should it be different?

What is T in the above return, and where should it come from? Should the developer provide this as it works with other typings or can it be inferred?

  1. What is the signature of resolve?
resolve(root, args, ctx, info)

What is root here, is this the type T from the above subscribe?

Is it reasonable that we require a resolve always be provided alongside the subscribe, even if it's just an identity function resolve: root => root

I don't think this should take too much to add, just wanted to be clear on the api we're looking for here.

Hi! In all my experience, field resolve is always useless. In subscribe filed, root is a document, which passed to pubsub.publish(name, payload) after subscription name. Also, in most cases, I'm using withFilter(asyncIterator: ()=> AsyncIterator, resolver: GraphQLFieldResolver): ResolverFn as value of subscribe, which allows to writing resolver with access logic and filtering. I'm really looking forward to the pull request being approved and merged.

Released this in 0.11 as "alpha" - it should work but it's undocumented / doesn't have an example or anything other than the code referenced above (PR's welcome).

Give it a shot and let me know if anything should be changed/is missing!

@tgriesser Great work! Just testing it out now! Isn't "Subscription" missing here?

I also don't see the subscriptionField being imported in the core file?

Anyways, just created #73 to solve this issue 馃憢

What is T in the above return, and where should it come from? Should the developer provide this as it works with other typings or can it be inferred?

  1. What is the signature of resolve?
resolve(root, args, ctx, info)

What is root here, is this the type T from the above subscribe?

Is it reasonable that we require a resolve always be provided alongside the subscribe, even if it's just an identity function resolve: root => root

I don't think this should take too much to add, just wanted to be clear on the api we're looking for here.

I just played around with this and noticed 2 things. Here is the example code:

export const USER_CREATED = 'USER_CREATED'
export interface IUserCreatedPayload {
  id: number
  username: string
}

export const User = objectType({
  name: 'User',
  definition: t => {
    t.int('id')
    t.string('username')
  },
})

export const UserCreated = subscriptionField('userCreated', {
  type: 'User',
  subscribe: (root, args, ctx) =>
    ctx.pubsub.asyncIterator<IUserCreatedPayload>([USER_CREATED]),
  resolve: payload => {
    return {
      id: 'test',
      username: undefined,
    }
  },
})

The first thing is that I expected payload to enforce that a value is returned that matched the given type, like it does with query / mutation resolvers.
However the code above does not error.

The second thing is that payload should be of type IUserCreatedPayload but is of type any.
When subscribe returns AsyncIterator<T>, then payload should be of typeT.

@tgriesser

Is ctx always guaranteed to be the same type as the one in normal query resolvers, or can/should it be different?

It is indeed likely to be different for subscriptions. We should add another option typegenAutoConfig.subscriptionContextType, which maybe defaults to contextType.

@tgriesser Any comments on this?

Is this available ?

Is this available ?

@justicejoe Yes it is. Here's a tutorial on how to use it: https://www.youtube.com/watch?v=tvqJfgK331M

Was this page helpful?
0 / 5 - 0 ratings

Related issues

saostad picture saostad  路  3Comments

bizmedia picture bizmedia  路  4Comments

santialbo picture santialbo  路  5Comments

ryands17 picture ryands17  路  4Comments

deadcoder0904 picture deadcoder0904  路  6Comments