Sangria GraphQL Library for Scala

repository·main·Indexed 24 days ago

https://github.com/sangria-graphql/sangria

A spec-compliant GraphQL library for Scala that enables the creation of GraphQL servers compatible with Apollo, Relay, and GraphiQL. It provides a comprehensive AST hierarchy for documents, schemas, and input values, along with tools for JSON marshalling via sangria-circe, execution result resolution, and error reporting using SourceMapper.

Tokens
5.4K
Snippets
6
Records
40
Agent score
84%

What's inside Sangria

  1. Update the release notes

    main
    After a release has been triggered, you can finalize the documentation by updating the GitHub release page. A draft release should be automatically prepared by the CI. You must edit this draft to set the correct released version and complete the release notes before saving.
  2. Install Sangria via SBT

    main

    To add Sangria to your Scala project using SBT, add the following dependency to your libraryDependencies. Replace <latest version> with the current version of Sangria.

    libraryDependencies += "org.sangria-graphql" %% "sangria" % "<latest version>"
  3. Release a new version of Sangria

    main

    Sangria uses an automated release process triggered by Git tags. To initiate a release, create a new annotated Git tag where the version string must start with a v. Once the tag is pushed to the origin, the CI pipeline will handle the release automatically. Note that publishing artifacts to Maven Central may take some time after the pipeline starts.

    git tag -a v0.1.0 -m "v0.1.0"
    git push origin v0.1.0
  4. Run Sangria benchmarks with sbt-jmh

    main

    Sangria benchmarks are executed using OpenJDK JMH and integrated into the build system via sbt-jmh.

    To run a full, standard benchmark suite, use:

    jmh:run

    When developing or debugging a new benchmark, you can use specific flags to reduce execution time by limiting iterations, warmups, forks, and threads.

  5. Understand the GraphQL AST hierarchy

    main

    The Sangria AST is built on a hierarchy of traits. All nodes implement AstNode, which provides a location (the lexical position in the source code).

    Core abstractions:

    • Definition: The building blocks of a Document. Includes OperationDefinition (executable operations like queries/mutations) and FragmentDefinition (reusable selection sets).
    • Selection: Components of a query. A SelectionContainer (like a Field or InlineFragment) contains a selections: Vector[Selection].
    • Type: Represents GraphQL types. Type can be a NamedType, NonNullType, or ListType. You can use .namedType on any Type to recursively find the underlying NamedType (stripping away list and non-null wrappers).
    • Value: Represents input values (scalars like IntValue, StringValue, BooleanValue, or complex types like ListValue and ObjectValue).
  6. How GraphQL Types and Input Types relate

    main

    Sangria distinguishes between OutputType (used for data returned by the server) and InputType (used for data provided by the client, like arguments or input objects).

    • LeafType: The most basic types, such as ScalarType or EnumType.
    • CompositeType: Types that contain other fields, such as ObjectType, InterfaceType, or UnionType.
    • InputType: A hierarchy for client-side data, including ScalarType, EnumType, InputObjectType, and wrappers like ListInputType or OptionInputType.
  7. How Schema, ObjectType, and InputObjectType relate

    main

    A Schema is the top-level container for a GraphQL service. It defines the entry points for execution: query, mutation, and subscription (all of which are ObjectTypes).

    • ObjectType: Represents the data structures returned by the server. They contain fields that resolve to other types.
    • InputObjectType: Represents the data structures sent by the client as arguments to fields or mutations.
    • Schema: Composes these types and includes global configuration like directives, validationRules, and additionalTypes (used to ensure all types in the graph are known).
  8. Understand the Context object in Sangria

    main

    The Context[Ctx, Val] class is the primary object provided during field resolution. It encapsulates everything a resolver needs to know about the current execution state for a specific field.

    Key Properties:

    • value: The object (parent) to which the current field belongs.
    • ctx: The user-provided execution context (passed to Sangria's execution method).
    • args: The arguments provided for this field.
    • schema: The GraphQL schema being executed.
    • field: The specific Field being resolved.
    • path: The ExecutionPath representing the location of this field in the query.
    • marshaller: The ResultMarshaller used for encoding results.
    • sourceMapper: An optional SourceMapper for mapping errors back to source locations.
    • deprecationTracker: An optional tracker for handling deprecated fields.

    Mental Model: Think of Context as the 'environment' for a single field. It bridges the gap between the raw GraphQL query (AST), the schema definitions, and your application's domain data (value).

  9. Define GraphQL Schema AST nodes

    main

    The AST includes types for representing a GraphQL schema (the type system). These are categorized as:

    • TypeSystemDefinition: Definitions of types (e.g., ScalarTypeDefinition, ObjectTypeDefinition, InterfaceTypeDefinition, UnionTypeDefinition, EnumTypeDefinition, InputObjectTypeDefinition).
    • TypeSystemExtensionDefinition: Extensions to existing types (e.g., ObjectTypeExtensionDefinition, InterfaceTypeExtensionDefinition, etc.).
    • SchemaDefinition: The root definition of a schema, specifying operationTypes (Query, Mutation, Subscription).
  10. Create a Hello World GraphQL application

    main

    This example demonstrates how to define a simple GraphQL schema using Sangria, a Query type with a single hello field, and execute a query using the Executor. This example uses sangria-circe for JSON marshalling.

    import sangria.schema._
    import sangria.execution._
    import sangria.macros._
    import sangria.marshalling.circe._
    import scala.concurrent.ExecutionContext.Implicits.global
    
    val QueryType = ObjectType("Query", fields[Unit, Unit](
      Field("hello", StringType, resolve = _ => "Hello world!")
    ))
    
    val schema = Schema(QueryType)
    
    val query = graphql"{ hello }"
    
    val result = Executor.execute(schema, query)
    
    result.foreach(res => println(res.spaces2))
  11. Configure the Sangria Parser with ParserConfig

    main

    The ParserConfig class allows you to customize how the GraphQL parser behaves, specifically regarding source mapping, comment parsing, and location tracking. You can create a custom configuration by instantiating ParserConfig or by using the provided helper methods on the default instance to derive new configurations.

    Configuration Options

    OptionTypeDefaultDescription
    experimentalFragmentVariablesBooleanfalseEnables experimental support for fragment variables.
    sourceIdFnParserInput => StringParserConfig.defaultSourceIdFnA function to generate a unique identifier for the source code.
    sourceMapperFnCodeSourceToSourceMapperFunctionParserConfig.defaultSourceMapperFnA function that maps a source identifier and ParserInput to a SourceMapper.
    parseLocationsBooleantrueWhether to parse location information (line/column) into the AST.
    parseCommentsBooleantrueWhether to parse comments into the AST.