Giter VIP home page Giter VIP logo

Comments (9)

schickling avatar schickling commented on May 24, 2024 11

There are multiple ways to accomplish this:

  1. By writing a custom AsyncIterator (see here)
  2. By using withFilter (see here)
  3. Implement the resolve method (see here):
 Subscription: {
    publications: {
      subscribe: async (parent, args, ctx, info) => {
        return ctx.db.subscription.post({ }, info)
      },
      resolve: (payload, args, context, info) => {
        // Manipulate and return the new value

        return payload;
      },
    },
  },

from prisma-binding.

marktani avatar marktani commented on May 24, 2024 1

Thanks so much! 🙏

from prisma-binding.

schickling avatar schickling commented on May 24, 2024 1

You're exactly right, @FredyC. This should be a lot easier and will in fact become easier once this issue is tackled: #118

from prisma-binding.

tbrannam avatar tbrannam commented on May 24, 2024

I'm confused how withFilter would function in conjunction of return ctx.db.subscription.post({ }, info) - most of the example use cases of withFilter are tied to returning an AsyncIterator - is that the responsibility of ctx.db.subscription somehow?

from prisma-binding.

tbrannam avatar tbrannam commented on May 24, 2024

withFilter seems to need some handholding to work as I would expect. withFilter requires a resolved AsyncIterator, but ctx.db.subscription.link returns a Promise - so you have to await. Finally I was surprised that I have to invoke the function filteredSubscription on the return - it feels like this is different than the usual examples that leverage PubSub - where the function itself is returned.

Can somebody help explain why this works, and if the syntax is expected?

  subscribe: async (parent, args, ctx, info) => {
    const subscription = await ctx.db.subscription.link(
      { },
      info,
    )

    filteredSubscription =  withFilter( () => subscription , (payload, variables) => {
      return true
    })

    return filteredSubscription()
  }

from prisma-binding.

danielkcz avatar danielkcz commented on May 24, 2024

I have another question related to this regarding the info. Consider the following where I want to return an actual type instead of that whole subscription payload as a client doesn't need to know other details about a subscription (eg. kind of mutation, changed fields...).

type Subscription {
  onFightStart: Fight!
}

# and query might look like...

subscription {
  onFightStart {
    id
    attackerId
  }
}

On the resolver side, it means that info argument is structured based on my input query and cannot be passed to ctx.db.subscription.fight({}, info) call directly. I need to somehow transform it so only relevant fields are being queried. I did found this article about demystifying the info, but it still looks like a lot of legwork and feels like shoving my hands to intestines of something not particularly appealing.

const onFightStart = {
  subscribe(_, args, ctx, info) {
    const fightIterator = await ctx.db.subscription.fight({}, /* how to build correct info here? */)
    const nextFight = async () => {
      const { value, done } = await fightIterator.next()
      // value is returned in { mutation, node } structure here, not what client wants
      const newValue = transformValueByInfo(value, info) // <-- not sure how do this
      return { value: newValue, done }
    }
    return { /* AsyncIterator juggling */ }
  }
}

I am aware that if I don't pass any info argument to prisma binding function, it will create one to contain every scalar field, but that doesn't work with subscriptions as an only scalar field is a mutation. I had also figured out it's possible to pass a query string to build that info object, but that's hardly flexible. Ideally I want to grab fields that client is asking for.

const selectionSet = `{
  mutation
  node {
    id
    attacker {
      id
    }
  }
}`
ctx.db.subscription.fight({}, selectionSet)

from prisma-binding.

timsuchanek avatar timsuchanek commented on May 24, 2024

@FredyC if I understood you correctly, you have a subscription to the underlying service like this:

type Subscription {
  fight: SubscriptionPayload
}

type SubscriptionPayload {
  ...
  node: Fight
}

and want to expose this:

type Subscription {
  fight: Fight
}

This means, that the info object of the resolver for the fight subscription will contain a query like this:

subscription {
  fight {
    id
  }
}

but the underlying service needs to receive this:

subscription {
  fight {
    node {
      id
    }
  }
}

In other words, the received query needs to be "embeded" into another query / we need to wrap it.

An API for this could look like this:

const onFightStart = {
  subscribe(_, args, ctx, info) {
    const fightIterator = await ctx.db.subscription.fight({}, wrapInfo(info, 'node'))
  },
  resolve(fight) {
    return fight.node
  }
}

@FredyC does that make sense to you?

from prisma-binding.

danielkcz avatar danielkcz commented on May 24, 2024

You are correct on input information. However, I want to watch for changes in different fields than those requested by the client. I did not realize that before mainly because subscriptions are a bit confusing about this. Data you request will be watched for changes and that's not always what you want.

const onFightStart = {
  subscribe(_, args, ctx, info) {
    const fightIterator = await ctx.db.subscription.fight({}, watchFragment) // <-- just a string to specify what to watch
    const nextFight = async () => {
      const { value, done } = await fightIterator.next()
      const fight = await ctx.db.query.fight({ where: { id: value.node.fightId } }, info) // <-- use info from client
      return { onFightStart: fight }
    }
    return { /* AsyncIterator juggling */ }
  }
}

I don't have any big issue with this right now, it's just kinda unintuitive and I had to spent quite some time to figuring that out and digging in the source code. I just hope that your breaking change in dotansimha/graphql-binding#80 won't prevent me doing this :)

from prisma-binding.

maticzav avatar maticzav commented on May 24, 2024

Hey 👋,

I believe the initial question has been well resolved throughout the conversation. In need for gaining a better overview of the issues facing the current version, I'll close it.

Feel free to reopen the issue if you believe we should further discuss its context. 🙂

from prisma-binding.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.