Juniper: Returning input types produces an invalid schema

Created on 2 May 2018  Â·  5Comments  Â·  Source: graphql-rust/juniper

If a field returns an input object, the program will compile/run fine, but produce an invalid schema. Here is a minimal proof of concept: https://github.com/ysimonson/juniper-poc/tree/returning-input-types

Running graphql get-schema against that branch will produce the error âš  Introspection must provide output type for fields..

bug

Most helpful comment

GraphQL has a pretty strict separation between Object and InputObject types.

I assume that's a lesson learned by Facebook: always enforce separate declaration of inputs and outputs to prevent reuse due to laziness and end up providing a non-optimal schema with nullable fileds that should'nt be, or the other way around.

I've come across this same problem too, though.
Custom scalars would be an option, but a pretty hacky one IMO if it's just to get around this restriction.

Personally I would just bite the bullet and define both types manually.
You can map them into the common type in your handlers and then keep your business logic in a separate layer from the Juniper/GraphQL logic.

That's would you should do anyway in most cases.

All 5 comments

Confirmed as bug.

The problem is, I don't see an easy way (that doesn't require quite a bit of refactoring) to ensure this invariant at compile time.

As a first step, would be rather easy to validate this at runtime on schema/RootNode creation.
I'll investigate that now.

Here's a little additional context in case it's helpful. I have a library that I'm experimenting adding juniper integration to. The challenge is that some structs can be both inputs and outputs.

e.g. this method takes in an EdgeQuery. An EdgeQuery may have EdgeKeys. But the method also returns EdgeKeys. So an EdgeKey is both returned by that method, and acts as an (indirect) argument to that method.

I'm trying to think of a workaround for this. There's two that come to mind:

1) Create a proc macro that allows you to define a struct, and it would create both an input and output variant. This would be non-trivial because it also needs to reference the appropriate input or output variant of its corresponding members. e.g. the the input variant of EdgeQuery would need to reference the input variant of EdgeKey.

2) Maybe it's possible to work around this by defining shared input/output types as scalars? I haven't looked into this too much because (as a GraphQL newbie) I'm guessing that would cause too much trouble for clients.

GraphQL has a pretty strict separation between Object and InputObject types.

I assume that's a lesson learned by Facebook: always enforce separate declaration of inputs and outputs to prevent reuse due to laziness and end up providing a non-optimal schema with nullable fileds that should'nt be, or the other way around.

I've come across this same problem too, though.
Custom scalars would be an option, but a pretty hacky one IMO if it's just to get around this restriction.

Personally I would just bite the bullet and define both types manually.
You can map them into the common type in your handlers and then keep your business logic in a separate layer from the Juniper/GraphQL logic.

That's would you should do anyway in most cases.

If anyone else hits this issue, I ended up going with @theduke's suggestion - i.e. manually defining the input/output types, and implementing From to easily switch between them and the actual models that the library uses. Doing it manually rather than using proc macros ended up being less headache than I worried. And having these dedicated input/output types allows fine-grained control over the GraphQL schema.

Came here due the same reason, leaving with the same commitment that the extra overhead right now, will be worth it in the long run.

Still too bad this can't/isn't a compile-time error though.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hrbigelow picture hrbigelow  Â·  5Comments

teymour-aldridge picture teymour-aldridge  Â·  5Comments

snnsnn picture snnsnn  Â·  4Comments

projektir picture projektir  Â·  4Comments

norcalli picture norcalli  Â·  6Comments