Skip to content

Commit

Permalink
Allow overriding builtin scalars
Browse files Browse the repository at this point in the history
  • Loading branch information
filosganga committed May 16, 2023
1 parent ee3864d commit 3bc1436
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,10 @@ class AstSchemaMaterializer[Ctx] private (
def getNamedType(
origin: MatOrigin,
typeName: String,
location: Option[AstLocation]): Type with Named =
typeDefCache.getOrElseUpdate(
origin -> typeName,
Schema.getBuiltInType(typeName).getOrElse {
location: Option[AstLocation]): Type with Named = {

def update = {
val builtType = {
val existing = existingDefsMat.get(typeName).toVector
val sdl = typeDefsMat.filter(_.name == typeName)
val additional = builder.additionalTypes.filter(_.name == typeName).toVector
Expand All @@ -606,11 +606,21 @@ class AstSchemaMaterializer[Ctx] private (
getNamedType(origin, allCandidates.head)
} else None

builtType.getOrElse(
throw MaterializedSchemaValidationError(Vector(
UnknownTypeViolation(typeName, Seq.empty, document.sourceMapper, location.toList))))
builtType
}

builtType
.orElse(Schema.getBuiltInType(typeName))
.getOrElse(throw MaterializedSchemaValidationError(Vector(
UnknownTypeViolation(typeName, Seq.empty, document.sourceMapper, location.toList))))

}

typeDefCache.getOrElseUpdate(
origin -> typeName,
update
)
}

def getNamedType(origin: MatOrigin, tpe: MaterializedType): Option[Type with Named] =
tpe match {
Expand Down
45 changes: 45 additions & 0 deletions modules/core/src/test/scala/sangria/schema/CustomScalarSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import java.text.SimpleDateFormat
import java.util.Date

import sangria.ast
import sangria.macros._
import sangria.util.Pos
import sangria.util.SimpleGraphQlSupport._
import sangria.validation.ValueCoercionViolation

import scala.util.{Failure, Success, Try}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import sangria.validation.BigDecimalCoercionViolation

class CustomScalarSpec extends AnyWordSpec with Matchers {
"Schema" should {
Expand Down Expand Up @@ -80,5 +82,48 @@ class CustomScalarSpec extends AnyWordSpec with Matchers {
Pos(3, 28)))
)
}

"allow to overwrite built-in scalar type" in {

def parseBigDecimal(s: String) = Try(BigDecimal(s)) match {
case Success(d) => Right(d)
case Failure(error) => Left(BigDecimalCoercionViolation)
}

val BigDecimalType = ScalarType[BigDecimal](
"BigDecimal",
description = Some("A string only BigDecimal type"),
coerceOutput = (d, _) => d.toString,
coerceUserInput = {
case s: String => parseBigDecimal(s)
case _ => Left(BigDecimalCoercionViolation)
},
coerceInput = {
case ast.StringValue(s, _, _, _, _) => parseBigDecimal(s)
case _ => Left(BigDecimalCoercionViolation)
}
)

val schemaSdl = graphql"""
scalar BigDecimal

type Query {
age: BigDecimal!
}
"""

val schema = Schema.buildFromAst[Unit](
schemaSdl,
AstSchemaBuilder.resolverBased(
ScalarResolver[Unit] { case ast.ScalarTypeDefinition("BigDecimal", _, _, _, _) =>
BigDecimalType
}
)
)

schema.scalarTypes.collectFirst { case ("BigDecimal", tpe) => tpe } should be(
Some(BigDecimalType))

}
}
}

0 comments on commit 3bc1436

Please sign in to comment.