Hi,
We've been using Sangria to create our company's first GraphQL APIs. We're a Scala Functional programming shop so we like doing everything monadic. We're doing our first schema that does a large number of fetches from DynamoDB tables to realize the result schema and I'm trying to use the Fetcher
type for each sub-table. This method expects a Future returned from the repository function while our is returning a higher-type of F[Seq[Software]]
. Have others been using Functional types with the Fetchers and Resolver caches? Sample code block below
def softwareFetcher[F[_]: Effect] =
Fetcher((repo: MasterRepo[F], ids: Seq[String]) => repo.devicesRepo.softwareByDeviceGuids(ids))(HasId(_.deviceGuid))
Correct me if I'm wrong, but...
I get the impression that https://github.com/sangria-graphql/sangria-akka-http-example is using https://github.com/graphql/graphql-playground and that the latter has been ended in favor of GraphiQL. graphql/graphql-playground#1143
I've incorporated GraphiQL into a Sangria server before using webjars. Is this something that needs to be done?
Following up on my previous question on union type, have made changes to return all possible types of union as a default case. But I wanted to add check based on the __typename requested for. I see in .js, objects are resolved based on the unique field name that each type has. Am looking for something equivalent in sangria.
__resolveType: obj => {
if (obj.reason) {
return "TimeoutError";
}
if (obj.field) {
return "ValidationError";
}
return null;
}
someUnionField
or, better yet, split this into two distinct fields rather than 1 that is a union type. Am I understanding correctly?{
someUnionField {
... on UnionTypeA {
someFieldOfTypeA
}
... on UnionTypeB {
someFieldOfTypeB
}
}
}
Executor.execute
), but so now that I have my user's identity and its roles, I don't really know what to do...SecureContext
really confuses me.SecureContext
that holds an Option[Identity]
defaulting to None
, and update that context after I retrieved my user's Identity, and then perform my access control against that updated context.beforeField
has my Context as parameter, my guess is that I can check the arguments passed, as one of them would be my userId , but let's assume the argument I want to check varies from one query to another (like, not necessarily called 'Id', or 'userId'), is there a way to use Middleware-based authorization anyway, or should I use Resolve-based authorization ?I don't think it's middleware VS resolve-based auth. We are using both for example.
The middleware checks that we are logged in.
The middleware also checks permissions based on tags:
val permissions = ctx.field.tags.collect { case Permission(p) => p }
if (permissions.nonEmpty && !secureContext.hasPermissions(permissions))
throw GraphQLOAuthException(OAuthError.insufficientScope(permissions))
And then, in some resolve functions, we also check the permissions:
resolve = (c: Context[SecureContext, Unit]) => {
if (!c.ctx.hasPermissions(....))
throw GraphQLOAuthException(OAuthError.insufficientScope)
case object JsonCoercionViolation extends ValueCoercionViolation("Not valid JSON")
implicit val JsonType: ScalarType[Any] = ScalarType[Any]("Json",
description = Some("Raw JSON value"),
coerceOutput = {
case (value: JsValue, c) => value
},
coerceUserInput = {
case v: String => Right(JsString(v))
case v: Boolean => Right(JsBoolean(v))
case v: Int => Right(JsNumber(v))
case v: Long => Right(JsNumber(v))
case v: Float => Right(JsNumber(v))
case v: Double => Right(JsNumber(v))
case v: BigInt => Right(JsNumber(BigDecimal(v)))
case v: BigDecimal => Right(JsNumber(v))
case v: JsValue => Right(v)
case _ => Left(JsonCoercionViolation)
},
coerceInput = {
case ast.StringValue(s, _, _, _, _) =>
Right(Json.parse(s))
case _ =>
Left(JsonCoercionViolation)
})
I'm puzzled as to why this variables
field in GraphQLHttpRequest
has a type parameter (and thus why GraphQLHttpRequest
itself does). It seems like this should just be represented as a Map[String,String]
, possibly empty.
case class GraphQLHttpRequest[T](
query: Option[String],
variables: Option[T],
operationName: Option[String])
How can we pass List[List[caseClass]] as argument ? When I am trying to do so, I am getting the following error: "spray.json.JsArray cannot be cast to scala.collection.Seq"
val fdsInputRequestFilter: InputObjectType[RequestFilter] = deriveInputObjectTypeRequestFilter
val requestFilter = Argument("filters", OptionInputType(ListInputType(ListInputType(fdsInputRequestFilter))))
Hi guys, thanks in advance for reading this. Does everyone know how to solve my problem?
I have a product data type in my code that looks like this:
final case class Choice(id: Int, name: String, option: ChoiceOption)
sealed trait ChoiceOption
object ChoiceOption {
final case class SingularChoiceOption(checked: Boolean) extends ChoiceOption
final case class MultipleChoiceOption(possibleValues: Seq[String], defaultValue: String) extends ChoiceOption
}
I want to represent this code in sangria as an interface:
interface Choice {
id: Int!
name: String!
}
type SingularChoice implements Choice {
id: Int!
name: String!
checked: Boolean!
}
type MultipleChoiceOption implements Choice {
id: Int!
name: String!
possibleValues: [String!]!
defaultValue: String!
}
but I don't want to write my code like this:
sealed trait Choice {
val id: Int
val name: String
}
final case class SingularChoiceOption(id: Int, name: String, checked: Boolean) extends Choice
final case class MultipleChoiceOption(id: Int, name: String, possibleValues: Seq[String], defaultValue: String) extends Choice
I'm using InterfaceType
for describing my Choice, but there're no constructors that resolve value as an interface subtype. In other words, I want to view product data type as a sum data type.
Does anyone know workarounds for this case? Thank you =).
In developing a Sangria example, I'm having difficulty in demonstrating even the most basic use of an SDL-based schema materialization. I'm getting
sangria.schema.SchemaMaterializationException: Can't extract value for a field 'User.id': not a map-like value.
when I use an SDL file containing
type User {
id: Long!
name: String!
person: Person!
}
I find it odd that ScalaInputUnmarshaller.isMapNode()
is true
only for Map
s, not for case classes, or that my User
case class doesn't get treated like a map. Wondering whether there's some linkage in the Scala code that I need.
The examples that I see tend to define the schema in Scala code. That has worked for me, but it obfuscates the schema's design. So it seems a real shame to do it that way.
Anyway, just mentioning the error for now, in case someone else has seen it. I'll have a clean example of the failure published soon.
InputObjectType
is used to represent a GraphQL type that can be used as an input, for example for an argument.