Fork me on GitHub
#graphql
<
2017-09-11
>
rickmoynihan09:09:47

@hlship: we’ve been playing with lacinia and it’s been really great so far… One thing I’d really like to do is support content negotiation formats other than JSON… In particular EDN but also others too (depending on the query). Is this currently possible with lacinia-pedestal?

hmaurer10:09:38

@rickmoynihan irrc lacinia-pedestal uses a multimethod to extract the query

hmaurer10:09:41

so yes it should be

rickmoynihan10:09:45

@hmaurer: is that for the request or the response? I meant the response, I should’ve been clearer.

hmaurer10:09:57

@rickmoynihan ah! that was for the request

rickmoynihan10:09:49

might be able to just assoc a new response interceptor over the existing one after constructing the server, but before starting it… not that familiar with pedestal though…

rickmoynihan10:09:04

yeah was thinking I could just dissoc that and add my own, that does some content-neg on the accept header, returning either json or EDN

rickmoynihan10:09:56

though I wonder if that would be a nice addition to lacinia-pedestal…

hmaurer10:09:43

@hlship was talking about adding the ability to easily customise interceptors

hmaurer10:09:52

I'm not sure where that went

andrewtropin12:09:31

I want to implement kebab case schema support for lacinia, it should not be very hard, but I want to make it working only when explicit flag to compile function provided, it's really needed for adding graphql to our project. Any suggestions from users/maintainers of lacinia?

hmaurer12:09:51

@andrewtropin why do you want to do this? GraphQL does not support kebab case, so I assume it’s only for aestetic reasons?

hmaurer12:09:34

it shouldn’t be necessary to implement this in lacinia

rickmoynihan12:09:12

I don’t particularly care about having kebab case, but I wish graphql had support for namespaces

rickmoynihan12:09:07

I think it would be good for interop if graphql would let you identify that a particular endpoint supported the schemas that your client requires. And that schemas could be shared, and think namespaces are basically a way to do that.

rickmoynihan12:09:59

for example the __ prefix seems like a bit of a hack in lieu of having proper namespace support.

andrewtropin12:09:10

@hmaurer We already have a huge codebase with REST api and kebab-cased names is all over the code. I want to do following: add graphql endpoint, keep all internals kebabish, add kebabed lacinia schema, but provide camelCase responses and accept camelCase request based on accept and content type headers. It will make all downstream apps like graphiql still working, but also allows us not to change existing codebase too much.

hmaurer12:09:52

@andrewtropin you can do it by converting back and forth between kebab case and camelCase in resolvers

andrewtropin12:09:59

Yes, I can, but it's necessary to do it in each resolver, which seems like copy-pasting, takes out params destructuring and other little, but annoying things.

hmaurer12:09:35

you can abstract it away in a function

hmaurer12:09:06

you could even automatically wrap each resolver in a function that does this conversation

hmaurer12:09:09

if that’s what you would like

hmaurer12:09:26

(I have the very problem you describe in my current project, and solved it in a similar way)

hmaurer12:09:59

in my case I need to convert between graphql field names and namespaced keywords

andrewtropin12:09:03

Thought about it, but it looks a little hacky, also will decrease perfomance.

hmaurer12:09:28

whether it’s implement in lacinia or in your code doesn’t matter much performance-wise

hmaurer12:09:48

and even then, I wouldn’t be worried about performance on this kind of operation unless you have huuuge input/outputs

hmaurer12:09:25

the time it takes to convert the keys of a small map to kebab case should be negligible compared to everything else happening in your app

hmaurer12:09:32

e.g. network delays on your API

andrewtropin13:09:17

There is some truth in your words : ) Anyway, It will be much simpler to have all internals in kebab case and only change case between delivering response then transforming data back and forth in many places (even automatically). Isn't it?

hmaurer13:09:54

I’m not sure; I quite like that the Lacinia schema is close to GraphQL’s conventions

hmaurer13:09:30

for example, in my case I not only want to do conversion to kebab-case, but I also want to namespace fields

hmaurer13:09:47

this does not translate to GraphQL (it does not support namespaces)

hmaurer13:09:17

I feel those things are best left to be implemented in userland, leaving Lacinia as an unopinionated implementation of GraphQL

hmaurer13:09:35

if you want to push those conversions as far out of your way as possible. write a function on the resolvers map (right before passing it to lacinia.util/attach-resolvers)

hmaurer13:09:58

you could wrap each resolver in a function which does the conversion on args and on the output

hmaurer13:09:21

then you won’t have to worry about it anywhere else in your app

hmaurer13:09:54

for the output, another option would be to override the default field resolver

hmaurer13:09:39

by default, Lacinia will resolve fields by doing something like (get object field-name)

hmaurer13:09:54

you can override this

hmaurer13:09:20

to do something like (get object (->kebab-case field-name))

hmaurer13:09:32

this won’t solve your input problem, but it will solve the output problem neatly

hmaurer13:09:01

for example:

hmaurer13:09:59

(defn keyword-field-resolver
  [field-name]
  (fn [_ _ obj] (get obj (->kebab-case field-name)))
)

(lacinia/compile schema {:default-field-resolver keyword-field-resolver})

andrewtropin13:09:06

@hmaurer Thanks a lot for those tips. Will think about such a way.

rickmoynihan15:09:26

@hmaurer: how are you handling namespaces? Do you just name your fields like myapp_somenamespace_fieldname and map them to myapp.somenamespace/fieldname by convention?

hmaurer16:09:51

My field names neve conflict, so I just drop the namespace and camelCase the field

hmaurer16:09:14

I store the namespaced keyword in the schema (under the field definition)

hmaurer16:09:36

and I have a function which, given input data and an input graphql type, re-constructs the namespaced-qualified map

rickmoynihan15:09:14

and do you do the same with enums etc?

rickmoynihan15:09:49

@hmaurer: sounds like you’re taking a similar approach to graphql as we are, i.e. dynamically generating schemas based on existing data

rickmoynihan16:09:21

the other approach to namespacing that occured to me would be to nest your stuff inside a field e.g.

{
   my_namespace {
      foo
      bar
      baz
   }
}

hmaurer20:09:15

mmh yes, that could be done

danielneal10:09:03

/users/hlship/dev

hlship16:09:31

Too often I type into the window my eyes are looking at, not the one with focus. Thus I sometimes have to change my passwords!