Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access data from resolvers from previous node #128

Open
NathanPB opened this issue Feb 15, 2021 · 3 comments
Open

Access data from resolvers from previous node #128

NathanPB opened this issue Feb 15, 2021 · 3 comments

Comments

@NathanPB
Copy link

NathanPB commented Feb 15, 2021

Hello, I don't know if I'm doing something wrong, but I'd like to access the data resolved in the previous nodes of an execution.

I'm sharing a schema to help demonstrate:

enum ContactVisibilty { PUBLIC, FRIENDS, PRIVATE }

type ContactField { 
  value: String!
  visibility: ContactVisibility!
}

type UserContact {
  discord: ContactField
  skype: ContactField
}

type UserProfile {
  uid: String!
  nickname: String!
  contact: UserContact!
  friends: [UserProfile!]!
}
enum<ContactVisibility>()
type<ContactField>()

type<UserContact> {
  property<ContactField?>("discord") {
    resolver { contact, ctx: Context ->
      // THIS POINT
      // Kotlin PSEUDOCODE
      val requested: UserProfile = ... // This is the profile of the user that is being requested, resolved in the previous nodes
      val requester: UserProfile = ctx.get<UserProfile>() // This is the profile of the user who made the request
      
      when (contact.visibility) {
        PUBLIC -> contact
        PRIVATE -> contact.takeIf { requested == requester } // If the user requested his own contact
        FRIENDS -> contact.takeIf { requested == requester || requested.areFriends(requester) } // If the user requested its own contact or a friend's contact
      }
    }
  }
  ...
}

type<UserProfile>() { ... }
query {
  users {
    contact {
      discord { value }
    }
  }
}

Let's say I want to, in the resolver of root (UserProfile) > contact > discord make checks that will need to use the data available in the root node (check if two users are friends to make the data available or null). How could I do that?

Thank you so much, great framework btw

NathanPB added a commit to NathanPB/WheresMyDuo that referenced this issue Feb 16, 2021
@NathanPB
Copy link
Author

NathanPB commented Feb 16, 2021

NathanPB added a commit to NathanPB/WheresMyDuo that referenced this issue Feb 16, 2021
@jeggy
Copy link
Member

jeggy commented Feb 16, 2021

I would say you should try to avoid structure like this. And have each resolver to be able to work on it's own. Example below would be how I would do it in a non document database:

data class UserProfile(val id: Int, val nickname: String)
data class UserContact(val userProfileId: Int, val discord: ContactField?, val skype: ContactField?, val ...)
data class ContactField(val value: String, val visibility: ContactVisibility)
...

query("getProfile") {
  resolver { -> UserProfile(1, "jeggy") }
}
type<UserProfile> {
  property<UserContact>("contact") {
    resolver { userProfile -> service.loadContactById(userProfile.id) }
  }
}
type<UserContact> {
  property<ContactField?>("discord") {
    resolver { contact ->
      val requester = ctx.get<UserProfile>()
      contact.discord?.takeIf {
        it.visibility.canView(service.loadUserProfileById(contact.userProfileId), requester?.uid)
      }
    }
  }
}

But ofcourse you are using mongo and kmongo (which I have very little experience with). It will probably be hard to change your data structure to have all the information needed without the need of knowing who the grandparent resolver returned.

@jeggy
Copy link
Member

jeggy commented Feb 16, 2021

But you how given scenarios for two new features that could be nice to have in KGraphQL, which are:

..
property<List<String>>("requestedFields") {
  resolver { contact, ctx: Context, node: Execution.Node ->
    node.getFields()
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants