walmartlabs / lacinia

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

Scalar type which returns vector #417

Closed jantorestolsvik closed 2 years ago

jantorestolsvik commented 2 years ago

Hi!

We have a custom scalar JSON which should be able to return anything that can be resolved to JSON. However we can not return vectors from a resolver with type JSON, because then we get the error that a single value was expected, but got a collection. A workaround is to have 2 nullable fields on the same object, value: JSON and values: JSON[]. That is a bit cumbersome. Is this something that we could change? I am used to it working from other frameworks, in javascript for example.

mszajna commented 2 years ago

A bit of a me too, but I find the single value check questionable for any field, not just scalars, and had it get in the way before when I was trying to have the parent object take the form of a Datomic lookup ref like [:user/id "mszajna"].

I suppose the reason we need this check is that Clojure is really permissive and (= (get [] :field) nil) instead of exception. This is particularly annoying for default resolvers (everything just silently nils out), but in this particular case the check could be moved to the default resolver itself. In case of user-defined resolvers it should be easy enough for the developer to spot the problem imho.

hlship commented 2 years ago

If this is a common problem, then it may be possible to defeat those checks with a schema compilation flag. It does mean that other programming errors will become harder to track down, but I think the problem of resolvers returning incorrect arity (single value vs. seq of values) is a minor one.

hlship commented 2 years ago

I'm going to think about this for a bit first.

hlship commented 2 years ago

The :disable-checks? schema compile option can be enabled (it is false by default); it removes the check that ensures that a single value is returned from a resolver that is not a list type.

This option was introduced for performance reasons, but should work well in your case, where a scalar type is, in fact, a seq or set. Of course, you'll need to provide :parse and :serialize for your scalar type that understands what to do.