From 0e7a290908bb29477e23e979ed84df97a9b46141 Mon Sep 17 00:00:00 2001 From: Amit Singh Date: Tue, 8 Aug 2023 12:43:08 +0530 Subject: [PATCH] make Blueprint.schema required (#275) --- .../tailcall/runtime/model/Blueprint.scala | 9 +-- .../runtime/service/StepGenerator.scala | 4 +- .../transcoder/Blueprint2Document.scala | 62 ++++++++++--------- .../runtime/transcoder/Config2Blueprint.scala | 2 +- .../transcoder/Document2Blueprint.scala | 29 +++++++-- 5 files changed, 62 insertions(+), 44 deletions(-) diff --git a/tailcall/src/main/scala/tailcall/runtime/model/Blueprint.scala b/tailcall/src/main/scala/tailcall/runtime/model/Blueprint.scala index c1d502db30..3b4e64c6a3 100644 --- a/tailcall/src/main/scala/tailcall/runtime/model/Blueprint.scala +++ b/tailcall/src/main/scala/tailcall/runtime/model/Blueprint.scala @@ -28,7 +28,7 @@ import scala.annotation.tailrec * is clearly defined. Once the IR is ready we will directly * compile IR to Caliban's Step ADT. */ -final case class Blueprint(definitions: List[Blueprint.Definition]) { +final case class Blueprint(definitions: List[Blueprint.Definition], schema: Blueprint.SchemaDefinition) { self => lazy val digest: Digest = Digest.fromBlueprint(self.sorted) @@ -45,11 +45,8 @@ final case class Blueprint(definitions: List[Blueprint.Definition]) { (r.name, r.fields.map(field => (field.name, field.resolver.map(_.compile))).toMap) }.toMap - def schema: Option[Blueprint.SchemaDefinition] = definitions.collectFirst { case s: Blueprint.SchemaDefinition => s } - def sorted: Blueprint = copy(definitions = definitions.sortBy { - case Blueprint.SchemaDefinition(_, _, _, _) => "a" case Blueprint.ScalarTypeDefinition(name, _, _) => "b" + name case Blueprint.UnionTypeDefinition(name, _, _, _) => "c" + name case Blueprint.EnumTypeDefinition(name, _, _, _) => "d" + name @@ -85,7 +82,7 @@ object Blueprint { def decode(bytes: CharSequence): Either[String, Blueprint] = codec.decodeJson(bytes) - def empty: Blueprint = Blueprint(Nil) + def empty: Blueprint = Blueprint(Nil, SchemaDefinition()) def encode(value: Blueprint): CharSequence = codec.encodeJson(value, None) @@ -142,7 +139,7 @@ object Blueprint { mutation: Option[String] = None, subscription: Option[String] = None, directives: List[Directive] = Nil, - ) extends Definition + ) final case class InputFieldDefinition( name: String, diff --git a/tailcall/src/main/scala/tailcall/runtime/service/StepGenerator.scala b/tailcall/src/main/scala/tailcall/runtime/service/StepGenerator.scala index bffab780f9..733a0e803b 100644 --- a/tailcall/src/main/scala/tailcall/runtime/service/StepGenerator.scala +++ b/tailcall/src/main/scala/tailcall/runtime/service/StepGenerator.scala @@ -49,12 +49,12 @@ object StepGenerator { ) )) val queryStep = for { - query <- blueprint.schema.flatMap(_.query) + query <- blueprint.schema.query qStep <- objectStepRef.get(query) } yield Step.QueryStep(withHeaders(qStep)) val mutationStep = for { - mutation <- blueprint.schema.flatMap(_.mutation) + mutation <- blueprint.schema.mutation mStep <- objectStepRef.get(mutation) } yield Step.QueryStep(withHeaders(mStep)) diff --git a/tailcall/src/main/scala/tailcall/runtime/transcoder/Blueprint2Document.scala b/tailcall/src/main/scala/tailcall/runtime/transcoder/Blueprint2Document.scala index 51390668cc..cd7416b300 100644 --- a/tailcall/src/main/scala/tailcall/runtime/transcoder/Blueprint2Document.scala +++ b/tailcall/src/main/scala/tailcall/runtime/transcoder/Blueprint2Document.scala @@ -20,35 +20,39 @@ trait Blueprint2Document { final def toDocument(blueprint: Blueprint): TValid[Nothing, CalibanDocument] = TValid.succeed { CalibanDocument( - blueprint.definitions.map { - case Blueprint.SchemaDefinition(query, mutation, subscription, directives) => CalibanDefinition - .TypeSystemDefinition - .SchemaDefinition(directives.map(toCalibanDirective(_)), query, mutation, subscription) - case Blueprint.ObjectTypeDefinition(name, fields, description, implements) => CalibanDefinition - .TypeSystemDefinition.TypeDefinition.ObjectTypeDefinition( - description, - name, - implements.map(tpe => CalibanType.NamedType(tpe.name, true)), - Nil, - fields.map(toCalibanField), - ) - case Blueprint.InputObjectTypeDefinition(name, fields, description) => CalibanDefinition.TypeSystemDefinition - .TypeDefinition.InputObjectTypeDefinition(description, name, Nil, fields.map(toCalibanInputValue)) - case Blueprint.ScalarTypeDefinition(name, directives, description) => CalibanDefinition.TypeSystemDefinition - .TypeDefinition.ScalarTypeDefinition(description, name, directives.map(toCalibanDirective(_))) - case Blueprint.EnumTypeDefinition(name, directives, description, values) => CalibanDefinition - .TypeSystemDefinition.TypeDefinition.EnumTypeDefinition( - description, - name, - directives.map(toCalibanDirective(_)), - values.map(toCalibanEnumValue(_)), - ) - case Blueprint.UnionTypeDefinition(name, directives, description, types) => CalibanDefinition - .TypeSystemDefinition.TypeDefinition - .UnionTypeDefinition(description, name, directives.map(toCalibanDirective(_)), types) - case Blueprint.InterfaceTypeDefinition(name, fields, description) => CalibanDefinition.TypeSystemDefinition - .TypeDefinition.InterfaceTypeDefinition(description, name, Nil, fields.map(toCalibanField)) - }, + List(CalibanDefinition.TypeSystemDefinition.SchemaDefinition( + blueprint.schema.directives.map(toCalibanDirective(_)), + blueprint.schema.query, + blueprint.schema.mutation, + blueprint.schema.subscription, + )) ++ + blueprint.definitions.map { + case Blueprint.ObjectTypeDefinition(name, fields, description, implements) => CalibanDefinition + .TypeSystemDefinition.TypeDefinition.ObjectTypeDefinition( + description, + name, + implements.map(tpe => CalibanType.NamedType(tpe.name, true)), + Nil, + fields.map(toCalibanField), + ) + case Blueprint.InputObjectTypeDefinition(name, fields, description) => CalibanDefinition + .TypeSystemDefinition.TypeDefinition + .InputObjectTypeDefinition(description, name, Nil, fields.map(toCalibanInputValue)) + case Blueprint.ScalarTypeDefinition(name, directives, description) => CalibanDefinition.TypeSystemDefinition + .TypeDefinition.ScalarTypeDefinition(description, name, directives.map(toCalibanDirective(_))) + case Blueprint.EnumTypeDefinition(name, directives, description, values) => CalibanDefinition + .TypeSystemDefinition.TypeDefinition.EnumTypeDefinition( + description, + name, + directives.map(toCalibanDirective(_)), + values.map(toCalibanEnumValue(_)), + ) + case Blueprint.UnionTypeDefinition(name, directives, description, types) => CalibanDefinition + .TypeSystemDefinition.TypeDefinition + .UnionTypeDefinition(description, name, directives.map(toCalibanDirective(_)), types) + case Blueprint.InterfaceTypeDefinition(name, fields, description) => CalibanDefinition.TypeSystemDefinition + .TypeDefinition.InterfaceTypeDefinition(description, name, Nil, fields.map(toCalibanField)) + }, SourceMapper.empty, ) } diff --git a/tailcall/src/main/scala/tailcall/runtime/transcoder/Config2Blueprint.scala b/tailcall/src/main/scala/tailcall/runtime/transcoder/Config2Blueprint.scala index e6f175e7a0..2b4f3aaef5 100644 --- a/tailcall/src/main/scala/tailcall/runtime/transcoder/Config2Blueprint.scala +++ b/tailcall/src/main/scala/tailcall/runtime/transcoder/Config2Blueprint.scala @@ -28,7 +28,7 @@ object Config2Blueprint { val rootSchema = Blueprint .SchemaDefinition(query = config.graphQL.schema.query, mutation = config.graphQL.schema.mutation) - for { definitions <- toDefinitions } yield Blueprint(rootSchema :: definitions) + for { definitions <- toDefinitions } yield Blueprint(definitions, rootSchema) } private def appendResolver( diff --git a/tailcall/src/main/scala/tailcall/runtime/transcoder/Document2Blueprint.scala b/tailcall/src/main/scala/tailcall/runtime/transcoder/Document2Blueprint.scala index 3008514862..88964a6a5d 100644 --- a/tailcall/src/main/scala/tailcall/runtime/transcoder/Document2Blueprint.scala +++ b/tailcall/src/main/scala/tailcall/runtime/transcoder/Document2Blueprint.scala @@ -32,12 +32,11 @@ trait Document2Blueprint { ) } - final private def toBlueprintDefinition(definition: Definition): TValid[String, Option[Blueprint.Definition]] = { + final def toBlueprintDefinition(definition: Definition): TValid[String, Option[Blueprint.Definition]] = { definition match { case _: Definition.ExecutableDefinition => TValid.fail("Executable definitions are not supported yet") case definition: Definition.TypeSystemDefinition => definition match { - case TypeSystemDefinition.SchemaDefinition(_, query, mutation, subscription) => TValid - .succeed(Option(Blueprint.SchemaDefinition(query, mutation, subscription))) + case TypeSystemDefinition.SchemaDefinition(_, _, _, _) => TValid.succeed(None) case _: TypeSystemDefinition.DirectiveDefinition => TValid.fail("Directive definitions are not supported yet") case definition: TypeSystemDefinition.TypeDefinition => definition match { case TypeDefinition.ObjectTypeDefinition(_, name, _, _, fields) => TValid @@ -56,8 +55,26 @@ trait Document2Blueprint { case _: Definition.TypeSystemExtension => TValid.fail("Type system extensions are not supported yet") } } + final private def toSchemaDefinition(definition: Definition): Option[Blueprint.SchemaDefinition] = + definition match { + case definition: TypeSystemDefinition => definition match { + case TypeSystemDefinition.SchemaDefinition(_, query, mutation, subscription) => + Option(Blueprint.SchemaDefinition(query, mutation, subscription)) + case _ => None + } + case _ => None + } - final def toBlueprint(document: Document): TValid[String, Blueprint] = - TValid.foreach(document.definitions)(toBlueprintDefinition(_)) - .map(defs => Blueprint(defs.collect { case Some(d) => d })) + final def toBlueprint(document: Document): TValid[String, Blueprint] = { + val schemaDefinition = + document.definitions.collectFirst { case d: TypeSystemDefinition => d }.flatMap(toSchemaDefinition(_)) match { + case Some(value) => TValid.succeed(value) + case None => TValid.fail("Schema definition is missing") + } + schemaDefinition.flatMap(sd => + TValid.foreach(document.definitions)(toBlueprintDefinition(_)) + .map(defs => Blueprint(defs.collect { case Some(d) => d }, sd)) + ) + + } }