sangria.ast.Document Scala Examples
The following examples show how to use sangria.ast.Document.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: DocumentInstancesSpec.scala From sbt-graphql with Apache License 2.0 | 5 votes |
package rocks.muki.graphql.instances import cats._ import cats.kernel.laws.discipline.MonoidTests import cats.tests.CatsSuite import org.scalacheck.{Arbitrary, Gen} import rocks.muki.graphql.codegen.style.sangria.TestSchema import sangria.ast.Document class DocumentInstancesSpec extends CatsSuite { implicit private val arbDocument: Arbitrary[Document] = Arbitrary( Gen.oneOf( Document(Vector.empty), Document.emptyStub, Document(TestSchema.StarWarsSchema.toAst.definitions.take(3)) ) ) implicit private val eqDocument: Eq[Document] = Eq.fromUniversalEquals[Document] checkAll("Monoid[sangria.ast.Document]", MonoidTests[Document].monoid) }
Example 2
Source File: SchemaLoader.scala From graphql-gateway with Apache License 2.0 | 5 votes |
package sangria.gateway.schema import better.files.File import sangria.ast.Document import sangria.execution.Executor import sangria.execution.deferred.DeferredResolver import sangria.gateway.AppConfig import sangria.gateway.file.FileUtil import sangria.gateway.http.client.HttpClient import sangria.gateway.schema.materializer.{GatewayContext, GatewayMaterializer} import sangria.gateway.util.Logging import sangria.parser.QueryParser import sangria.schema.Schema import sangria.marshalling.circe._ import scala.concurrent.{ExecutionContext, Future} import scala.util.control.NonFatal import scala.util.{Failure, Success} class SchemaLoader(config: AppConfig, client: HttpClient, mat: GatewayMaterializer)(implicit ec: ExecutionContext) extends Logging { def loadSchema: Future[Option[SchemaInfo[GatewayContext, Any]]] = { val files = FileUtil.loadFiles(config.watch.allFiles, config.watch.allGlobs) if (files.nonEmpty) { val parsed = files.map { case (path, content) ⇒ path → QueryParser.parse(content) } val failed = parsed.collect {case (path, Failure(e)) ⇒ path → e} if (failed.nonEmpty) { failed.foreach { case (path, error) ⇒ logger.error(s"Can't parse file '$path':\n${error.getMessage}") } Future.successful(None) } else { val successful = parsed.collect {case (path, Success(doc)) ⇒ path → doc} val document = Document.merge(successful.map(_._2)) try { val info = for { ctx ← GatewayContext.loadContext(config, client, document) schema = Schema.buildFromAst(document, mat.schemaBuilder(ctx).validateSchemaWithException(document)) intro ← executeIntrospection(schema, ctx) } yield Some(SchemaInfo( schema, ctx, (), Nil, DeferredResolver.empty, schema.renderPretty, intro, files.map(_._1))) info.recover(handleError(files)) } catch { case e if handleError(files).isDefinedAt(e) ⇒ Future.successful(handleError(files)(e)) } } } else { logger.error("No schema files found!") Future.successful(None) } } private def handleError(files: Vector[(File, String)]): PartialFunction[Throwable, Option[SchemaInfo[GatewayContext, Any]]] = { case NonFatal(e) ⇒ logger.error(s"Can't create the schema from files: ${files.map(_._1).mkString(", ")}. " + e.getMessage) None } private def executeIntrospection(schema: Schema[GatewayContext, Any], ctx: GatewayContext) = Executor.execute(schema, sangria.introspection.introspectionQuery(schemaDescription = false, directiveRepeatableFlag = false), ctx) }
Example 3
Source File: GraphQLRequestUnmarshaller.scala From graphql-gateway with Apache License 2.0 | 5 votes |
package sangria.gateway.http import java.nio.charset.Charset import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.server.Directive0 import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller} import akka.util.ByteString import sangria.ast.Document import sangria.parser.QueryParser import sangria.renderer.{QueryRenderer, QueryRendererConfig} import scala.collection.immutable.Seq object GraphQLRequestUnmarshaller { val `application/graphql` = MediaType.applicationWithFixedCharset("graphql", HttpCharsets.`UTF-8`, "graphql") def explicitlyAccepts(mediaType: MediaType): Directive0 = headerValuePF { case Accept(ranges) if ranges.exists(range ⇒ !range.isWildcard && range.matches(mediaType)) ⇒ ranges }.flatMap(_ ⇒ pass) def includeIf(include: Boolean): Directive0 = if (include) pass else reject def unmarshallerContentTypes: Seq[ContentTypeRange] = mediaTypes.map(ContentTypeRange.apply) def mediaTypes: Seq[MediaType.WithFixedCharset] = List(`application/graphql`) implicit final def documentMarshaller(implicit config: QueryRendererConfig = QueryRenderer.Compact): ToEntityMarshaller[Document] = Marshaller.oneOf(mediaTypes: _*) { mediaType ⇒ Marshaller.withFixedContentType(ContentType(mediaType)) { json ⇒ HttpEntity(mediaType, QueryRenderer.render(json, config)) } } implicit final val documentUnmarshaller: FromEntityUnmarshaller[Document] = Unmarshaller.byteStringUnmarshaller .forContentTypes(unmarshallerContentTypes: _*) .map { case ByteString.empty ⇒ throw Unmarshaller.NoContentException case data ⇒ import sangria.parser.DeliveryScheme.Throw QueryParser.parse(data.decodeString(Charset.forName("UTF-8"))) } }
Example 4
Source File: QueryGQL.scala From cornichon with Apache License 2.0 | 5 votes |
package com.github.agourlay.cornichon.http import cats.Show import cats.syntax.show._ import com.github.agourlay.cornichon.json.CornichonJson.parseDslJsonUnsafe import io.circe.{ Encoder, Json } import sangria.ast.Document import sangria.renderer.QueryRenderer case class QueryGQL( url: String, query: Document, operationName: Option[String], variables: Option[Map[String, Json]], params: Seq[(String, String)], headers: Seq[(String, String)]) { def withParams(params: (String, String)*) = copy(params = params) def addParams(params: (String, String)*) = copy(params = this.params ++ params) def withHeaders(headers: (String, String)*) = copy(headers = headers) def addHeaders(headers: (String, String)*) = copy(headers = this.headers ++ headers) def withQuery(query: Document) = copy(query = query) def withOperationName(operationName: String) = copy(operationName = Some(operationName)) def withVariables(newVariables: (String, VarValue)*) = { val vars: Map[String, Json] = newVariables.map { case (k, v) => k -> parseDslJsonUnsafe(v.value)(v.encoder, v.show) }.toMap copy(variables = variables.fold(Some(vars))(v => Some(v ++ vars))) } lazy val querySource = query.source.getOrElse(QueryRenderer.render(query, QueryRenderer.Pretty)) lazy val payload: String = { import io.circe.generic.auto._ import io.circe.syntax._ GqlPayload(querySource, operationName, variables).asJson.show } private case class GqlPayload(query: String, operationName: Option[String], variables: Option[Map[String, Json]]) } trait VarValue { type Value def value: Value def encoder: Encoder[Value] def show: Show[Value] } object VarValue { implicit def fromEncoderShow[A: Encoder: Show](a: A): VarValue = new VarValue { type Value = A def value = a def encoder = Encoder[A] def show = Show[A] } } object QueryGQL { val emptyDocument = Document(Vector.empty) }
Example 5
Source File: UpdateTypeAndFieldPositions.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.system.mutactions.internal import cool.graph.Types.Id import cool.graph._ import cool.graph.shared.models.{Client, Project} import cool.graph.system.database.finder.{CachedProjectResolver, ProjectQueries, ProjectResolver} import sangria.ast.{Document, ObjectTypeDefinition, TypeDefinition} import scaldi.{Injectable, Injector} import slick.dbio.DBIOAction import slick.jdbc.MySQLProfile.backend.DatabaseDef import scala.collection.immutable.Seq import scala.collection.mutable import scala.concurrent.Future case class UpdateTypeAndFieldPositions( project: Project, client: Client, newSchema: Document, internalDatabase: DatabaseDef, projectQueries: ProjectQueries )(implicit inj: Injector) extends SystemSqlMutaction with Injectable { import scala.concurrent.ExecutionContext.Implicits.global implicit val projectResolver = inject[ProjectResolver](identified by "uncachedProjectResolver") val mutactions: mutable.Buffer[SystemSqlMutaction] = mutable.Buffer.empty override def execute: Future[SystemSqlStatementResult[Any]] = refreshProject.flatMap { project => val newTypePositions: Seq[Id] = newSchema.definitions.collect { case typeDef: TypeDefinition => project .getModelByName(typeDef.name) .orElse(project.getEnumByName(typeDef.name)) .map(_.id) }.flatten mutactions += UpdateProject( client = client, oldProject = project, project = project.copy(typePositions = newTypePositions.toList), internalDatabase = internalDatabase, projectQueries = projectQueries, bumpRevision = false ) mutactions ++= newSchema.definitions.collect { case typeDef: ObjectTypeDefinition => project.getModelByName(typeDef.name).map { model => val newFieldPositions = typeDef.fields.flatMap { fieldDef => model.getFieldByName(fieldDef.name).map(_.id) }.toList UpdateModel(project = project, oldModel = model, model = model.copy(fieldPositions = newFieldPositions)) } }.flatten val y = mutactions.map(_.execute) Future.sequence(y).map { statementResults => val asSingleAction = DBIOAction.sequence(statementResults.toList.map(_.sqlAction)) SystemSqlStatementResult(sqlAction = asSingleAction) } } def refreshProject: Future[Project] = { projectResolver.resolve(project.id).map(_.get) } override def rollback: Option[Future[SystemSqlStatementResult[Any]]] = mutactions.map(_.rollback).headOption.flatten }
Example 6
Source File: SchemaDiff.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.system.migration.dataSchema import sangria.ast.Document import scala.util.Try object SchemaDiff { def apply(oldSchema: String, newSchema: String): Try[SchemaDiff] = { for { oldDocParsed <- SdlSchemaParser.parse(oldSchema) newDocParsed <- SdlSchemaParser.parse(newSchema) } yield SchemaDiff(oldDocParsed, newDocParsed) } } case class SchemaDiff( oldSchema: Document, newSchema: Document ) { import DataSchemaAstExtensions._ val addedTypes: Vector[String] = newSchema.oldTypeNames diff oldSchema.typeNames val removedTypes: Vector[String] = oldSchema.typeNames diff newSchema.oldTypeNames val updatedTypes: Vector[UpdatedType] = { val x = for { typeInNewSchema <- newSchema.objectTypes typeInOldSchema <- oldSchema.objectTypes.find(_.name == typeInNewSchema.oldName) } yield { val addedFields = typeInNewSchema.fields.filter(fieldInNewType => typeInOldSchema.fields.forall(_.name != fieldInNewType.oldName)) val removedFields = typeInOldSchema.fields.filter(fieldInOldType => typeInNewSchema.fields.forall(_.oldName != fieldInOldType.name)) val updatedFields = (typeInNewSchema.fields diff addedFields).map { updatedField => UpdatedField(updatedField.name, updatedField.oldName, updatedField.fieldType.namedType.name) } UpdatedType( name = typeInNewSchema.name, oldName = typeInNewSchema.oldName, addedFields = addedFields.map(_.name).toList, removedFields = removedFields.map(_.name).toList, updatedFields = updatedFields.toList ) } x.filter(_.hasChanges) } val addedEnums: Vector[String] = newSchema.oldEnumNames diff oldSchema.enumNames val removedEnums: Vector[String] = oldSchema.enumNames diff newSchema.oldEnumNames val updatedEnums: Vector[UpdatedEnum] = { for { typeInNewSchema <- newSchema.enumTypes typeInOldSchema <- oldSchema.enumTypes.find(_.name == typeInNewSchema.oldName) } yield UpdatedEnum(name = typeInNewSchema.name, oldName = typeInOldSchema.name) } } case class UpdatedType( name: String, oldName: String, addedFields: List[String], removedFields: List[String], updatedFields: List[UpdatedField] ) { def hasChanges: Boolean = addedFields.nonEmpty || removedFields.nonEmpty || updatedFields.nonEmpty } case class UpdatedField( name: String, oldName: String, newType: String ) case class UpdatedEnum( name: String, oldName: String )
Example 7
Source File: RelationDiff.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.system.migration.dataSchema import cool.graph.Types.Id import cool.graph.shared.models.{Project, Relation} import sangria.ast.{Document, StringValue} object RelationDiff { // a schema is said to contain a relation if a @relation directive exists with correct name, or // a @relation with different name links the same fields def schemaContainsRelation(project: Project, schema: Document, relation: Relation): Boolean = { import DataSchemaAstExtensions._ if (schema.containsRelation(relation.name)) { true } else { try { val leftModel = schema.objectType_!(relation.getModelA_!(project).name) val leftFieldRelationDirectiveName = leftModel .field_!(relation.getModelAField_!(project).name) .directive_!("relation") .argument_!("name") .value val rightModel = schema.objectType_!(relation.getModelB_!(project).name) val rightFieldRelationDirectiveName = rightModel .field_!(relation.getModelBField_!(project).name) .directive_!("relation") .argument_!("name") .value leftFieldRelationDirectiveName .asInstanceOf[StringValue] .value == rightFieldRelationDirectiveName.asInstanceOf[StringValue].value } catch { case e: Throwable => false } } } // project is said to contain relation if a relation with the name already exists // or the two fields are already linked by a relation with other name def projectContainsRelation(project: Project, addRelation: AddRelationAction): Boolean = { project.relations.exists { relation => if (relation.name == addRelation.input.name) { true } else { try { val leftModelRelationId: Option[Id] = project .getModelById_!(addRelation.input.leftModelId) .getFieldByName_!(addRelation.input.fieldOnLeftModelName) .relation .map(_.id) val rightModelRelationId: Option[Id] = project .getModelById_!(addRelation.input.rightModelId) .getFieldByName_!(addRelation.input.fieldOnRightModelName) .relation .map(_.id) leftModelRelationId == rightModelRelationId } catch { case e: Throwable => false } } } } }
Example 8
Source File: UserContext.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.client import cool.graph.client.database.ProjectDataresolver import cool.graph.shared.models.{AuthenticatedRequest, AuthenticatedUser, Project, ProjectWithClientId} import cool.graph.RequestContextTrait import sangria.ast.Document import scaldi.{Injectable, Injector} case class UserContext(project: Project, authenticatedRequest: Option[AuthenticatedRequest], requestId: String, requestIp: String, clientId: String, log: Function[String, Unit], override val queryAst: Option[Document] = None, alwaysQueryMasterDatabase: Boolean = false)(implicit inj: Injector) extends RequestContextTrait with UserContextTrait with Injectable { override val projectId: Option[String] = Some(project.id) val userId = authenticatedRequest.map(_.id) val queryDataResolver = new ProjectDataresolver(project = project, requestContext = this) val mutationDataresolver = { val resolver = new ProjectDataresolver(project = project, requestContext = this) resolver.enableMasterDatabaseOnlyMode resolver } def dataResolver = if (alwaysQueryMasterDatabase) { mutationDataresolver } else { queryDataResolver } } object UserContext { def load( project: Project, requestId: String, requestIp: String, clientId: String, log: Function[String, Unit], queryAst: Option[Document] = None )(implicit inj: Injector): UserContext = { UserContext(project, None, requestId, requestIp, clientId, log, queryAst = queryAst) } def fetchUserProjectWithClientId( project: ProjectWithClientId, authenticatedRequest: Option[AuthenticatedRequest], requestId: String, requestIp: String, log: Function[String, Unit], queryAst: Option[Document] )(implicit inj: Injector): UserContext = { fetchUser(project.project, authenticatedRequest, requestId, requestIp, project.clientId, log, queryAst) } def fetchUser( project: Project, authenticatedRequest: Option[AuthenticatedRequest], requestId: String, requestIp: String, clientId: String, log: Function[String, Unit], queryAst: Option[Document] = None )(implicit inj: Injector): UserContext = { val userContext = UserContext(project, authenticatedRequest, requestId, requestIp, clientId, log, queryAst = queryAst) if (authenticatedRequest.isDefined && authenticatedRequest.get.isInstanceOf[AuthenticatedUser]) { userContext.addFeatureMetric(FeatureMetric.Authentication) } userContext } } trait UserContextTrait { val project: Project val authenticatedRequest: Option[AuthenticatedRequest] val requestId: String val clientId: String val log: Function[String, Unit] val queryAst: Option[Document] = None }
Example 9
Source File: SubscriptionQueryValidator.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.subscriptions.schemas import cool.graph.shared.models.{Model, ModelMutationType, Project} import org.scalactic.{Bad, Good, Or} import sangria.ast.Document import sangria.parser.QueryParser import sangria.validation.QueryValidator import scaldi.Injector import scala.util.{Failure, Success} case class SubscriptionQueryError(errorMessage: String) case class SubscriptionQueryValidator(project: Project)(implicit inj: Injector) { def validate(query: String): Model Or Seq[SubscriptionQueryError] = { queryDocument(query).flatMap(validate) } def validate(queryDoc: Document): Model Or Seq[SubscriptionQueryError] = { for { modelName <- modelName(queryDoc) model <- modelFor(modelName) _ <- validateSubscriptionQuery(queryDoc, model) } yield model } def queryDocument(query: String): Document Or Seq[SubscriptionQueryError] = QueryParser.parse(query) match { case Success(doc) => Good(doc) case Failure(_) => Bad(Seq(SubscriptionQueryError("The subscription query is invalid GraphQL."))) } def modelName(queryDoc: Document): String Or Seq[SubscriptionQueryError] = QueryTransformer.getModelNameFromSubscription(queryDoc) match { case Some(modelName) => Good(modelName) case None => Bad(Seq(SubscriptionQueryError("The provided query doesn't include any known model name. Please check for the latest subscriptions API."))) } def modelFor(model: String): Model Or Seq[SubscriptionQueryError] = project.getModelByName(model) match { case Some(model) => Good(model) case None => Bad(Seq(SubscriptionQueryError("The provided query doesn't include any known model name. Please check for the latest subscriptions API."))) } def validateSubscriptionQuery(queryDoc: Document, model: Model): Unit Or Seq[SubscriptionQueryError] = { val schema = SubscriptionSchema(model, project, None, ModelMutationType.Created, None, true).build val violations = QueryValidator.default.validateQuery(schema, queryDoc) if (violations.nonEmpty) { Bad(violations.map(v => SubscriptionQueryError(v.errorMessage))) } else Good(()) } }
Example 10
Source File: SubscriptionUserContext.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.subscriptions import cool.graph.RequestContextTrait import cool.graph.client.UserContextTrait import cool.graph.deprecated.actions.schemas.MutationMetaData import cool.graph.client.database.ProjectDataresolver import cool.graph.shared.models.{AuthenticatedRequest, Project} import sangria.ast.Document import scaldi.{Injectable, Injector} case class SubscriptionUserContext(nodeId: String, mutation: MutationMetaData, project: Project, authenticatedRequest: Option[AuthenticatedRequest], requestId: String, clientId: String, log: Function[String, Unit], override val queryAst: Option[Document] = None)(implicit inj: Injector) extends UserContextTrait with RequestContextTrait with Injectable { override val isSubscription: Boolean = true override val projectId: Option[String] = Some(project.id) val dataResolver = new ProjectDataresolver(project = project, requestContext = this) override val requestIp: String = "subscription-callback-ip" // todo: get the correct ip from server }
Example 11
Source File: GraphQLHandler.scala From daml with Apache License 2.0 | 5 votes |
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. // SPDX-License-Identifier: Apache-2.0 package com.daml.navigator import akka.actor.ActorRef import akka.http.scaladsl.model.StatusCode import akka.http.scaladsl.model.StatusCodes._ import com.daml.navigator.graphql._ import com.daml.navigator.graphql.SprayMarshallers._ import com.daml.navigator.model.PartyState import com.daml.navigator.store.Store.StoreException import com.typesafe.scalalogging.LazyLogging import sangria.ast.Document import sangria.execution._ import sangria.parser.QueryParser import sangria.renderer.SchemaRenderer import sangria.schema.Schema import spray.json._ import scala.concurrent.{ExecutionContext, Future} import scala.util.Try case class ParseResult(ast: Document, operationName: Option[String], variables: JsValue) trait GraphQLHandler { def schema: Schema[GraphQLContext, Unit] def parse(request: String): Try[ParseResult] def parse(request: JsValue): Try[ParseResult] def executeQuery(parsed: ParseResult, party: PartyState): Future[(StatusCode, JsValue)] def renderSchema: String } object GraphQLHandler { type ParseQuery = JsValue => Try[ParseResult] type ExecuteQuery = (ParseResult, PartyState) => Future[(StatusCode, JsValue)] type CustomEndpoints = Set[CustomEndpoint[_]] } case class DefaultGraphQLHandler( customEndpoints: GraphQLHandler.CustomEndpoints, platformStore: Option[ActorRef])( implicit executionContext: ExecutionContext ) extends GraphQLHandler with LazyLogging { def schema: Schema[GraphQLContext, Unit] = new GraphQLSchema(customEndpoints).QuerySchema def parse(request: String): Try[ParseResult] = Try(request.parseJson).flatMap(parse) def parse(request: JsValue): Try[ParseResult] = for { fields <- Try(request.asJsObject.fields) JsString(query) <- Try(fields("query")) operationName = fields.get("operationName").collect { case JsString(value) => value } vars: JsValue = fields.get("variables") match { case Some(obj: JsObject) => obj case _ => JsObject.empty } ast <- QueryParser.parse(query) } yield ParseResult(ast, operationName, vars) def executeQuery(parsed: ParseResult, party: PartyState): Future[(StatusCode, JsValue)] = { platformStore.fold[Future[(StatusCode, JsValue)]]( Future.successful(InternalServerError -> JsString("Platform store not available")) )(store => { val context = GraphQLContext(party, store) Executor .execute( schema, parsed.ast, context, variables = parsed.variables, operationName = parsed.operationName, exceptionHandler = ExceptionHandler { case (_, StoreException(message)) => HandledException(message) } ) .map(OK -> _) .recover { case error: QueryAnalysisError => logger.warn(s"GraphQL analysis error ${error.getMessage}.") BadRequest -> error.resolveError case error: ErrorWithResolver => logger.error("Failed to execute GraphQL query", error) InternalServerError -> error.resolveError } }) } def renderSchema: String = SchemaRenderer.renderSchema(schema) }
Example 12
Source File: DocumentLoader.scala From sbt-graphql with Apache License 2.0 | 5 votes |
package rocks.muki.graphql.codegen import java.io.File import cats.implicits._ import rocks.muki.graphql.instances.monoidDocument import sangria.ast.Document import sangria.parser.QueryParser import sangria.schema._ import sangria.validation.QueryValidator import scala.io.Source object DocumentLoader { def single(schema: Schema[_, _], file: File): Result[Document] = for { document <- parseDocument(file) violations = QueryValidator.default.validateQuery(schema, document) _ <- Either.cond( violations.isEmpty, document, Failure(s"Invalid query in ${file.getAbsolutePath}:\n${violations.map(_.errorMessage).mkString(", ")}") ) } yield document private def parseSchema(file: File): Result[Schema[_, _]] = for { document <- parseDocument(file) schema <- Either.catchNonFatal(Schema.buildFromAst(document)).leftMap { error => Failure(s"Failed to read schema $file: ${error.getMessage}") } } yield schema private def parseDocument(file: File): Result[Document] = for { input <- Either.catchNonFatal(Source.fromFile(file).mkString).leftMap { error => Failure(s"Failed to read $file: ${error.getMessage}") } document <- Either.fromTry(QueryParser.parse(input)).leftMap { error => Failure(s"Failed to parse $file: ${error.getMessage}") } } yield document }
Example 13
Source File: instances.scala From sbt-graphql with Apache License 2.0 | 5 votes |
package rocks.muki.graphql import cats.Monoid import io.circe.Json import sangria.ast.Document import sangria.marshalling.InputUnmarshaller package object instances { implicit object CirceInputUnmarshaller extends InputUnmarshaller[Json] { def getRootMapValue(node: Json, key: String) = node.asObject.get(key) def isMapNode(node: Json) = node.isObject def getMapValue(node: Json, key: String) = node.asObject.get(key) def getMapKeys(node: Json) = node.asObject.get.keys def isListNode(node: Json) = node.isArray def getListValue(node: Json) = node.asArray.get def isDefined(node: Json) = !node.isNull def getScalarValue(node: Json) = { def invalidScalar = throw new IllegalStateException(s"$node is not a scalar value") node.fold( jsonNull = invalidScalar, jsonBoolean = identity, jsonNumber = num => num.toBigInt orElse num.toBigDecimal getOrElse invalidScalar, jsonString = identity, jsonArray = _ => invalidScalar, jsonObject = _ => invalidScalar ) } def getScalaScalarValue(node: Json) = getScalarValue(node) def isEnumNode(node: Json) = node.isString def isScalarNode(node: Json) = node.isBoolean || node.isNumber || node.isString def isVariableNode(node: Json) = false def getVariableName(node: Json) = throw new IllegalArgumentException("variables are not supported") def render(node: Json) = node.noSpaces } }
Example 14
Source File: GraphQlController.scala From tap with Apache License 2.0 | 5 votes |
package controllers import javax.inject.Inject import models.GraphqlSchema import models.graphql.GraphqlActions import play.api.Logger import play.api.libs.json.{JsObject, JsValue, Json} import play.api.mvc.{Action, AnyContent, InjectedController, Result} import sangria.ast.Document import sangria.execution.{ErrorWithResolver, Executor, QueryAnalysisError} import sangria.marshalling.playJson.{PlayJsonInputUnmarshallerJObject, PlayJsonResultMarshaller} import sangria.parser.{QueryParser, SyntaxError} import sangria.schema.Schema import views.GraphiqlPage import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Failure, Success} class GraphQlController @Inject() (assets: AssetsFinder, gqlSchema: GraphqlSchema, actions: GraphqlActions) extends InjectedController { val schema:Schema[GraphqlActions,Unit] = gqlSchema.create def graphiql:Action[AnyContent] = Action { request => Logger.info("Got Any content request from:" + request.remoteAddress) //Ok(views.html.graphiql(assets)) Ok(GraphiqlPage.render("Explore TAP with GraphiQL")) } def graphql:Action[JsValue] = Action.async(parse.json) { request => val query = (request.body \ "query").as[String] val operation = (request.body \ "operationName").asOpt[String] val variables = (request.body \ "variables").asOpt[JsObject].getOrElse(Json.obj()) Logger.info(s"Query received from ${request.remoteAddress} >>> ${operation.getOrElse("No query")}") Logger.info(s"Variables: $variables") process(query,operation,variables) } def process(query:String,name:Option[String],variables:JsObject):Future[Result] = QueryParser.parse(query) match { case Success(queryAst) => executeGraphQLQuery(queryAst, name, variables) case Failure(error: SyntaxError) => Future.successful(BadRequest(error.getMessage)) case _ => Future.successful(BadRequest("There was a problem with the request to TAP graphql.")) } def executeGraphQLQuery(query: Document, name: Option[String], vars: JsObject):Future[Result] = { Executor.execute(schema, query, actions, operationName = name, variables = vars) .map(Ok(_)) .recover { case error: QueryAnalysisError => BadRequest(error.resolveError) case error: ErrorWithResolver => InternalServerError(error.resolveError) } } }
Example 15
Source File: DeliverySchemeSpec.scala From sangria with Apache License 2.0 | 5 votes |
package sangria.parser import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec class DeliverySchemeSpec extends AnyWordSpec with Matchers { "DeliveryScheme" should { "by default support `Try`" in { import scala.util.{Success, Failure} QueryParser.parse("{ field }") shouldBe a [Success[_]] QueryParser.parse("}") shouldBe a [Failure[_]] } "support `Either`" in { import sangria.parser.DeliveryScheme.Either import scala.util.{Left, Right} QueryParser.parse("{ field }") shouldBe a [Right[_, _]] QueryParser.parse("}") shouldBe a [Left[_, _]] } "support exception throwing" in { import sangria.parser.DeliveryScheme.Throw import sangria.ast.Document QueryParser.parse("{ field }") shouldBe a [Document] a [SyntaxError] should be thrownBy QueryParser.parse("}") } } }
Example 16
Source File: package.scala From sangria with Apache License 2.0 | 5 votes |
package sangria import scala.language.experimental.{macros => `scalac, please just let me do it!`} import sangria.ast.{Document, InputDocument, Value} package object macros { implicit class LiteralGraphQLStringContext(val sc: StringContext) extends AnyVal { def gql(args: Any*): Document = macro ParseMacro.impl def gqlInp(args: Any*): Value = macro ParseMacro.implInput def gqlInpDoc(args: Any*): InputDocument = macro ParseMacro.implInputDoc def graphql(args: Any*): Document = macro ParseMacro.impl def graphqlInput(args: Any*): Value = macro ParseMacro.implInput def graphqlInputDoc(args: Any*): InputDocument = macro ParseMacro.implInputDoc } }
Example 17
Source File: package.scala From drunk with Apache License 2.0 | 5 votes |
package com.github.jarlakxen.drunk import sangria.ast.{ Document, Field, FragmentDefinition, FragmentSpread, OperationDefinition, Selection } package object ast { val TypenameFieldName = "__typename" val TypenameField = Field( None, TypenameFieldName, Vector.empty, Vector.empty, Vector.empty) def addTypename(doc: Document): Document = { val newDefinitions = doc.definitions.map { case op: OperationDefinition => addTypename(op) case frag: FragmentDefinition => addTypename(frag) case other => other } doc.copy(definitions = newDefinitions) } private def addTypename(op: OperationDefinition): OperationDefinition = { val newSelections = op.selections.map(addTypename) op.copy(selections = newSelections) } private def addTypename(frag: FragmentDefinition): FragmentDefinition = { val newSelections = frag.selections.map(addTypename) if (newSelections.exists(s => s.isInstanceOf[Field] && s.asInstanceOf[Field].name == TypenameFieldName)) { frag.copy(selections = newSelections) } else { frag.copy(selections = TypenameField +: newSelections) } } private def addTypename(select: Selection): Selection = { select match { case field: Field if field.selections.nonEmpty => addTypename(field) case other => other } } private def addTypename(field: Field): Field = { var hasTypename = false val newSelections = field.selections.map { case field: Field if field.selections.nonEmpty => if (field.name == TypenameFieldName) { hasTypename = true } addTypename(field) case frag: FragmentSpread => hasTypename = true frag case other => other } if (!hasTypename) { field.copy(selections = TypenameField +: newSelections) } else { field.copy(selections = newSelections) } } }
Example 18
Source File: QueryComplexityFilter.scala From naptime with Apache License 2.0 | 5 votes |
package org.coursera.naptime.ari.graphql.controllers.filters import javax.inject.Inject import javax.inject.Singleton import com.typesafe.scalalogging.StrictLogging import org.coursera.naptime.ari.Response import org.coursera.naptime.ari.graphql.GraphqlSchemaProvider import org.coursera.naptime.ari.graphql.SangriaGraphQlContext import org.coursera.naptime.ari.graphql.controllers.GraphQLController import org.coursera.naptime.ari.graphql.marshaller.NaptimeMarshaller._ import org.coursera.naptime.ari.graphql.resolvers.NaptimeResolver import org.coursera.naptime.ari.graphql.resolvers.NoopResolver import play.api.libs.json.JsObject import play.api.libs.json.Json import play.api.mvc.Results import sangria.ast.Document import sangria.execution.ErrorWithResolver import sangria.execution.Executor import sangria.execution.QueryAnalysisError import sangria.execution.QueryReducer import scala.concurrent.ExecutionContext import scala.concurrent.Future @Singleton class QueryComplexityFilter @Inject()( graphqlSchemaProvider: GraphqlSchemaProvider, configuration: ComplexityFilterConfiguration)(implicit executionContext: ExecutionContext) extends Filter with Results with StrictLogging { val MAX_COMPLEXITY = configuration.maxComplexity def apply(nextFilter: FilterFn): FilterFn = { incoming => computeComplexity(incoming.document, incoming.variables) .flatMap { complexity => if (complexity > MAX_COMPLEXITY) { Future.successful( OutgoingQuery( response = Json.obj("error" -> "Query is too complex.", "complexity" -> complexity), ariResponse = None)) } else { nextFilter.apply(incoming) } } .recover { case error: QueryAnalysisError => OutgoingQuery(error.resolveError.as[JsObject], None) case error: ErrorWithResolver => OutgoingQuery(error.resolveError.as[JsObject], None) case error: Exception => OutgoingQuery(Json.obj("errors" -> Json.arr(error.getMessage)), None) } } private[graphql] def computeComplexity(queryAst: Document, variables: JsObject)( implicit executionContext: ExecutionContext): Future[Double] = { // TODO(bryan): is there a way around this var? var complexity = 0D val complReducer = QueryReducer.measureComplexity[SangriaGraphQlContext] { (c, ctx) => complexity = c ctx } val executorFut = Executor.execute( graphqlSchemaProvider.schema, queryAst, SangriaGraphQlContext(null, null, executionContext, debugMode = false), variables = variables, exceptionHandler = GraphQLController.exceptionHandler(logger), queryReducers = List(complReducer), deferredResolver = new NoopResolver()) executorFut.map { _ => complexity } } } case class ComplexityFilterConfiguration(maxComplexity: Int) object ComplexityFilterConfiguration { val DEFAULT = ComplexityFilterConfiguration(100000) }
Example 19
Source File: SangriaGraphQLSupport.scala From incubator-s2graph with Apache License 2.0 | 5 votes |
package org.apache.s2graph.http import java.nio.charset.Charset import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} import akka.http.scaladsl.model._ import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller} import akka.util.ByteString import sangria.ast.Document import sangria.parser.QueryParser import sangria.renderer.{QueryRenderer, QueryRendererConfig} trait SangriaGraphQLSupport { private val mediaTypes: Seq[MediaType.WithFixedCharset] = Seq(MediaType.applicationWithFixedCharset("graphql", HttpCharsets.`UTF-8`, "graphql")) private val unmarshallerContentTypes: Seq[ContentTypeRange] = mediaTypes.map(ContentTypeRange.apply) implicit def documentMarshaller(implicit config: QueryRendererConfig = QueryRenderer.Compact): ToEntityMarshaller[Document] = { Marshaller.oneOf(mediaTypes: _*) { mediaType ⇒ Marshaller.withFixedContentType(ContentType(mediaType)) { json ⇒ HttpEntity(mediaType, QueryRenderer.render(json, config)) } } } implicit val documentUnmarshaller: FromEntityUnmarshaller[Document] = { Unmarshaller.byteStringUnmarshaller .forContentTypes(unmarshallerContentTypes: _*) .map { case ByteString.empty ⇒ throw Unmarshaller.NoContentException case data ⇒ import sangria.parser.DeliveryScheme.Throw QueryParser.parse(data.decodeString(Charset.forName("UTF-8"))) } } }