walmartlabs / lacinia

GraphQL implementation in pure Clojure
http://lacinia.readthedocs.io/en/latest/
Other
1.82k stars 162 forks source link

API for identifying selections from application context #65

Closed hlship closed 7 years ago

hlship commented 7 years ago

The application context passed to a field resolver function includes a key ::lacinia/selections, that identifies the field selections for the field.

We don't, and probably should not, publish the details of the structure of this value (as it is quite valuable to keep it private, opaque, and subject to change).

However, it exists so that field resolvers can preview the selections that may occur on the resolved value.

The canonical example of this is a resolver that performs a SQL database query, and may customize the request based on what is requested, for example, to optionally include a join only if the data from the join is needed.

I would suggest something like the following:

(selects-field? context :User/permissions) => true

This would scan the selections inside the context for any reference to the :permissions field of the :User object.

Another useful function might be:

(selections context) => #{:User/first_name :User/last_name :User:born_on :User/permissions :Permission/name}

I'm struggling with how this might work in the context of unions and interfaces; I would guess that the collection of these extended field names would driven by fragments, and ultimately, the fragments would identify the specific object fields.

stijnopheide commented 7 years ago

We are using lacinia selections in a different way and not sure if that is as intended or whether this proposal will have any influence on that.

Our mutation resolvers for updating/creating content are very generic. On these resolvers we use [:com.walmartlabs.lacinia/selection :field-definition :args] and translate each argument into (a part of) a datomic transaction. We decorate our :input-objects with some information about the namespace of the datomic attribute and how relations should be constructed. If an input-object has a field that is not a scalar type, we'll look up the type in the schema and do this conversion recursively.

So, in short: we would need some way of identifying the type of the arguments being passed into the mutation resolver. On the other hand I think we could also do this by passing those types as a parameter of the resolver factory. So if the selection API is not public, we are going to change this before upgrading to 0.17.0.

hlship commented 7 years ago

We don't want to commit to freezing the format of the selection tree. For example, we're thinking about using more namespaced keywords for keys. And, over the course of the last couple of dot releases, we've added a couple of new keys to various schema definitions, and to the selection nodes.

I would say that the right way to do this is using field resolvers, which will have direct access to the arguments.

Again, back this up to your actual requirement: "We need the types of the argument values inside our field resolver." That's something that could be accomplished, either as meta data on the args map, or as an additional key in the supplied context.