morpheus-graphql icon indicating copy to clipboard operation
morpheus-graphql copied to clipboard

Provide a safe `unsafeInternalContext` method

Open th3coop opened this issue 4 years ago • 2 comments

Background: We're federating a multiple backend APIs into one through Morhpeus. Because of how we're reshaping internal API data into new formats so it makes more sense to the users that will interact with the endpoint we have an argument for our top level resolver buried a few layers down inside the query structure.

High level "code": The query looks like this:

{
  project(org="...", name="..."){
      commit(id="some-long-uuid")
         sources {
            url
        }
    }
}

Behind the scenes, the source we retrieve the data to resolve those queries is retrieved from another graphql endpoint and all in one query (so 'project' and 'commit' are returned in one query). Because of this, we need the id argument for the commit portion of the query in the top level resolver.

Right now we're using Data.Morpheus.Types.unsafeInternalContext to dig down into the query and retrieve the commit ID but we are obviously worried about depending on that code since it's clear we shouldn't be using it.

The Question: Do you have plans to create a "safe" unsafeInternalContext or is there already a safe way to do what we're doing?

Apologies if this is the wrong forum to even be asking this. Please let me know if I should move my question elsewhere.

th3coop avatar Jul 23 '21 22:07 th3coop

hi @th3coop, i considering for future to write class like that.

class Viewer a where
  parent :: m a
  args :: GQLType args => m args
  children :: m a

or even extend SelectionTree to allow you that.

however for now you could use closures to cover your case.

nalchevanidze avatar Aug 07 '21 09:08 nalchevanidze

@nalchevanidze, that looks very much like what I was thinking as well. I'm not sure if this is appropriate but I had a very good experience working with some graph like structures in our front end using this Elm Tree Library. What you describe looks like the Zipper type that the author used for traversing and searching the Tree.

When you say I could use closure to accomplish this for now, do you mean using unsafeInternalContext to get Data.Morpheus.Types.ResolverContext then descend into the currentSelection to find the SelectionSet that has the arguments i'm looking for?

Like so, where getSubSelectionArg is essentially the closure:

Data.Morpheus.Types.ResolverContext { currentSelection } <- MorpheusTypes.unsafeInternalContext
let commit_id = getSubSelectionArg "commit" "commit_id" currentSelection

getSubSelectionArg uses a recursive loop to search the tree for the Selection with the desired args.

th3coop avatar Aug 17 '21 18:08 th3coop