Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Nick Hudkins
@nickhudkins
Have an example I can take a look at?
Or, any chance you could fork: https://github.com/sangria-graphql/sangria-akka-http-example and recreate the issue? The only time Circe and Sangria "interact" is when it is being materialized. Are you using Json WITHIN your resolvers?
Miklos Szots
@smiklos
Here is one
case class ResultData(resultId: ResultId)

object ResultId {

  //Already derived it as a string
  //This is a factory for creating ResultId from String
  implicit val encoder: Encoder[ResultId] = Encoder.encodeString.contramap(_.id)
  implicit val decoder: Decoder[ResultId] = Decoder.decodeString.map(ResultId(_))

  //Now I repeat myself
  //This is also a factory for creating ResultId from String
  implicit val graphQlType = ScalarAlias[ResultId, String](
    StringType,
    _.id,
    id => Right(ResultId(id))
  )
}

case class ResultId(id: String) extends AnyVal
Nick Hudkins
@nickhudkins
Ah, ok, so you would hope that by defining the ScalarAlias, that you'd get your encoder / decoders for whatever marshalling library you're using correct?
Miklos Szots
@smiklos
well, that would be ideal isn't it. Not whatever, I'm more than happy if it only supports circe (;> )
Nick Hudkins
@nickhudkins
Haha :) ok, let me give some thought to that.
Miklos Szots
@smiklos
We could possibly create a conversion from sangria type to circe or the other way around. The tricky thing in both cases is that both sangria and circe is more than happy to compile when using auto derivation without any of these extra implicits. a bit better solution would be to be able to derive one of the encoder/decoder pairs from the other. A lot better solution would be when sangria generates marshaller, it would auto derive circe encoders
Nick Hudkins
@nickhudkins
ya, we already "have" to do this as we marshall / unmarshall input and output types: https://github.com/sangria-graphql/sangria-circe/blob/master/src/main/scala/sangria/marshalling/circe.scala#L92-L104
Yann Simon
@yanns
I'm not 100% but circe should never be used when parsing the query. The json library is only used when creating the payload to send over the wire.
Nick Hudkins
@nickhudkins
Absolutely. I think @smiklos's use case is that, is that if a custom scalar exists, you might need to convert to and from... within your application
outside of accepting it as input, and rendering it as output
My "does this seem like something Sangria (or json support for sangria) should handle" screams... no, because Sangria doesn't have any care about that.
Miklos Szots
@smiklos
even more often we use scalar aliases. trying to keep the input already prevalidated by enfocing contstraints (like strong types, lengths of string etc).
It just feels strange that I need to tell circe that it should encode/decode those types differently when I already did tell sangria about it
I totally understand the separation of concerns here but that doesn't fix the usability of it. It just feels strange. Somehow being generic clashes with being convenient
Nick Hudkins
@nickhudkins
I still am not sure what the use case is here
in your case, let's say you don't define the encoder and decoder...
if a resolver indicates a field as a ResultId.graphqlType, and you return a string from said resolver, it will be coerced according to your toScalar function id => Right(ResultId(id))
Miklos Szots
@smiklos
Then circe will believe that I sent the input json as
{
 resultId: {
   id: "something"
}
instead of 
{
resultId: "something"
}
and so it will fail
Nick Hudkins
@nickhudkins
I think I'm back to being confused :) lol
Miklos Szots
@smiklos
my use case is that I want to abuse scala aliases because that's the recommended approach according to the docs. Turning simple scalars to narrower/valid types.
But because of that, I also need to tame circe derivation at the same time. Have I always accepted Strings and numbers, it would all be fine
:D
Nick Hudkins
@nickhudkins
Just to be clear, we are talking about InputTypes right?
Miklos Szots
@smiklos
yes
Nick Hudkins
@nickhudkins
ok, so then I believe you're not looking for ScalaAlias, but instead, need the FromInput type classes
or sorry... ToInput, or possibly both, my brain is scrambled
Miklos Szots
@smiklos

I tihnk that's something the circe support takes care of already.

I do work with scalarAliases as I though that's needed for input objects as well

since they define a conversion both to and from
I expect sangria that it uses these aliases to take simple String values from the request and turn them into something better , or fail otherwise
Now we have this better type, it's time to make a case class (that is the input object) out of it. Yet, without also declaring circe decoder for the type, circe fails to decode as it didn't get the memo from sangria that the field was already parsed and validated
so perhaps, the problem is that for Circe to go from AST to Case class also needs to know how to take that scalar value and convert it to the field on the case class. This makes sense, this is default circe behavior. But, sangria took over that responsibility when it started parsing the request and doing validations. IT clearly does that, since it makes use of these scalar types and scalar aliases
Miklos Szots
@smiklos
input json -> sangria-parser (via circe) -> String -> scalar alias -> ResultId
but when it's time to put this ResultId into a case class it seems we start over
input json -> circe -> case class
very important to mention, (perhaps a bit late) that I'm strictly talking about deriveInputObject and not manually creating the fields
Nick Hudkins
@nickhudkins
If you can give me a full example, I think I may be able to help
This IS important :)
what's your deriveInputObject call look like?
Miklos Szots
@smiklos
import io.circe.{Decoder, Encoder}
import sangria.macros.derive.deriveInputObjectType
import sangria.schema.{ScalarAlias, StringType}

case class ResultData(resultId: ResultId)

object ResultData {

  implicit val derived = deriveInputObjectType[ResultData]()
}

object ResultId {

  //Already derived it as a string
  //This is a factory for creating ResultId from String
  implicit val encoder: Encoder[ResultId] = Encoder.encodeString.contramap(_.id)
  implicit val decoder: Decoder[ResultId] = Decoder.decodeString.map(ResultId(_))

  //Now I repeat myself
  //This is also a factory for creating ResultId from String
  implicit val graphQlType: ScalarAlias[ResultId, String] = ScalarAlias[ResultId, String](
    StringType,
    _.id,
    id => Right(ResultId(id))
  )
}

case class ResultId(id: String) extends AnyVal
Miklos Szots
@smiklos
I've literally added a println to both decoder and alias and they both get invoked :D , the graphql is invoked even twice
to get one value mapping, 3 invocation :/
removed circe decoder
 "Argument 'test' has invalid value: Attempt to decode value on failed cursor: DownField(id),DownField(resultId) (line 4, column 18):\n   testing(test: {\n                 ^",
so , I need a scalar alias so sangira generates a valid input/output object (for wrapper classes) but I also need to actually map it and tell circe how to do it.
Funny enough, the graphql type gets invoked 2 times here as well, and only circe fails
Miklos Szots
@smiklos
looking at the marshaller, it's clear that creating a case class uses the json node parsed straight out of the request and that whatever sangria does with that value is out of the hands of circe. It all makes sense, just using the lib is confusing
Oliver Wetterau
@owetterau

Does anybody have an idea, why enums and Circe are failing with an "argument xyzzy has invalid value: CNil" error?

As far as I have followed it up, it seems that a case class containing an enum (whereas the enum has no quotes in GraphQL-JSON) is being read properly (including the enum), then being converted to a new JSON where the enum is treated as a string (with quotes) and it seems that it then shall be converted to a case class where it fails because the enum value is now being read with quotes and cannot be converted to an Enum. Unfortunately I don't know how to change that behavior.

I am using EnumType(...)and deriveInputObjectType[...] to create the schema.

Does it have to do with the issues you have been describing with Circe in the last posts?

Dan Di Spaltro
@dispalt
@nickhudkins well the actual issue is just how it all ties together. Like circe's decoders and encoders are not introspectable. so if you make a custom decoder/encoder in circe because you've renamed a field or something, the derivation for the input object wouldn't reflect that. It's not a bug per se, and nothing really sangria can do about it, it just limits the usefulness
Nick Hudkins
@nickhudkins
Yeah :( I was looking at it now, creating a bit of a test case
@dispalt the question I have is... can deriveInputObjectType, ensure that the proper (encoding / decoding) implicits are in scope along with the graphql type
Nick Hudkins
@nickhudkins
As time has gone on, I know many folks who maybe used to use Sangria, no longer do. I was curious if we could get a quick list of "Companies using Sangria at scale" If anyone here is using it in production at work (and you can share) I'd love to collect a list!
Yann Simon
@yanns
Hi, I gave a talk about GraphQL that you might find interesting: https://www.youtube.com/watch?v=Y4aP-ryulgQ&t=489s
Srepfler Srdan
@schrepfler
as any project, it would be good if there's a leadership with a clear roadmap ahead. What differentiates Sangria from the other implementations, what will keep it relevant in time etc.