Fork me on GitHub
#graphql
<
2017-12-08
>
hlship00:12:05

:interceptors defaults to the result of calling graphql-interceptors

hlship00:12:30

That's a map of interceptor name to interceptor map. You can replace keys in the map, or add new keys/interceptors to the map.

hlship00:12:58

There's additional functions in com.walmartlabs.lacinia.pedestal.interceptors to allow you to set dependencies, to control the order of execution of the interceptors.

admay04:12:59

@hlship How do union type in Lacinia work? I’m trying to get one working but keep getting the error, “Field resolver returned an instance not tagged with a schema type.” My resolver looks like so,

(def resolve-client
  ^ResolverResult
  (fn [context args _value]
    (resolve-as
      (if-let [client (db/client args)]
        client
        {:message "Client does not exist"}))))
My union type is that of either a client or an error where error is just a message of type String.

admay04:12:50

Never mind, I got it to work! I’m not sure if this is the most efficient way or the correct way, but for those who are interested…

(def resolve-client
  ^ResolverResult
  (fn [context args _value]
    (resolve-as
      (if-let [client (db/client args)]
        (tag-with-type client :Client)
        (tag-with-type {:message "Client does not exist"} :Error)))))
tag-with-type is from the com.walmartlabs.lacinia.schema namespace. ResolverResult and resolve-as are from the com.walmartlabs.lacinia.resolve namespace

guy09:12:14

So i believe with resolve-as its as simple as providing a second argument and that turns it into an error

guy09:12:34

(def resolve-client
  ^ResolverResult
  (fn [context args _value]
    (resolve-as
      (if-let [client (db/client args)]
        client
        "Client does not exit" {:message "Client does not exist"}))))

guy09:12:49

So that would return a resolver result with an error inside of it

guy09:12:00

I’ve not used tag-with-type before, that looks interesting

andrewtropin12:12:54

Can I use composite types for field arguments?

guy12:12:53

Can you give an example of what you mean

andrewtropin12:12:05

:get-token           {:type    :Token
                        :args    {:authdata    {:type :AuthData}
                                  ;; :password {:type :String}
                                  }
                        :resolve :authn/get-token}

guy12:12:59

yes i believe you can

andrewtropin12:12:00

:objects
......
  :AuthData
  {:fields {:login    {:type :String}
            :password {:type :String}}}

guy12:12:07

but i think you need to make it an input-object?

andrewtropin12:12:39

oh, thanks a lot

andrewtropin12:12:51

Exactly what I watching for

guy12:12:55

well it might not be mandatory

guy12:12:58

but i think its useful

guy12:12:07

because you can have something like

guy12:12:15

:AuthDataInput

guy12:12:25

and mirror the updateable fields in the object

guy12:12:29

if that makes sense?

andrewtropin12:12:07

yep, I'm agreed with separate entity for input objects.

guy12:12:37

If you use a graphiql plugin it might break it

guy12:12:58

i think some of the graphiql plugins get quite picky about every thing have descriptions and things

andrewtropin12:12:19

Works as expected

guy12:12:32

:thumbsup:

hlship18:12:08

I would code it as:

(if-let [client (db/client args)]
      client
      (resolve-as nil {:message "Client does not exist."}))
Returning a String when expecting to return a resolved object value is likely to cause other problems.

guy18:12:19

Interesting

guy18:12:27

What does providing a nil do instead?

hlship18:12:12

It ensures that Lacinia doesn't try to select any nested fields. Further, this use makes it clear that "just client" is the normal flow, and resolve-as is the failure path.

guy18:12:32

Thats great

guy18:12:46

So then potentially you will only get :errors with that message map inside of it?

hlship18:12:56

Returning a string will result in Lacinia attempting to select fields inside the String; I believe that would be either an internal exception or a flurry of errors added to the response.

guy18:12:20

Yeah i get errors more to do with the object fields being missing

guy18:12:37

so for example if a user had a non null id, and i throw an error when it should be a user

guy18:12:44

it would say error non null field is null

guy18:12:53

would i still get that with nil?

hlship18:12:57

You may be your explicit error and (I believe) an additional error if the field type is non-null.

hlship18:12:23

But you shouldn't use the non-null qualifier on the type, if there's a possibility that it is not available as in this case.

guy18:12:57

So how do you handle mutations that go wrong?

guy18:12:39

(if that makes sense)

hlship18:12:41

Same way. When things go wrong, (resolve-as nil error). The big question is what goes in the error map.

guy18:12:00

So say i had a mutation on an object which had non-null fields. Should the fields be not non-null, if theres a chance that if the mutation breaks it will return nil

guy18:12:23

(reads a bit like a tongue twister sorry)

hlship18:12:43

No, you would be ok. The logic is: - invoke the field resolver - If it returns nil and the type has non-null then add an error - if it returns non-nil, perform sub-selections So the fact that sub-selection fields are non-null is irrelevant, Lacinia doesn't go down that path.

guy18:12:22

oki dokie thanks!