### HTTP4s Server Setup for GraphQL API Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/db-backed-model.md Sets up the http4s server to expose the GraphQL API. It combines the services for both in-memory and database-backed models and binds them to a port. ```scala def services(xa: Transactor[IO]): List[HttpRoutes[IO]] = { val dbMapping = WorldMapping.schema.withRoot(WorldMapping.root).withTypeMappings(WorldMapping.typeMappings) val dbElaborator = WorldMapping.elaborator(dbMapping) val dbGraphQL = GraphQLService(dbElaborator) List(GraphQL.routes(dbGraphQL, "world")) } ``` -------------------------------- ### GraphQL Query Example: Nested Friends Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md An example GraphQL query demonstrating nested friend relationships to show how cycles in the data can be traversed. ```graphql query { character(id: 1000) { name friends { name friends { name } } } } ``` -------------------------------- ### GraphQL Query Example: Character and Friends Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md An example GraphQL query to retrieve a character by ID and their friends' names. This demonstrates nested querying within the schema. ```graphql query { character(id: 1002) { name friends { name } } } ``` -------------------------------- ### Main Application Entry Point with Docker DB Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/db-backed-model.md The `run` method in `Main.scala` starts the application, including a Dockerized PostgreSQL database, and exposes the GraphQL API for both in-memory and database-backed models. ```scala @main def run(args: String*): Unit = { val db = Resource.eval(DockerContainer.postgres).flatMap(_.configure).map(_.host).unsafeRunSync() val dbConfig = "jdbc:postgresql://" + db + "/world" val xa = Transactor.fromDriverManager[IO]( "org.postgresql.Driver", dbConfig, "postgres", "postgres") val services = DemoServer.services(xa) val app = services.foldLeft(HttpApp.empty)(_.combine(_)) println(s"GraphQL API available at http://localhost:8080/graphql") println(s"GraphQL Playground available at http://localhost:8080/playground.html?endpoint=world") Ember.serve(8080, app).use(_ => IO.never).drain } ``` -------------------------------- ### Running the Star Wars Demo Application Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md Instructions on how to start the http4s-based demo application from the SBT REPL using sbt-revolver. This application hosts the in-memory and db-backend models and a GraphQL client. ```bash sbt:root> demo/reStart [info] Application demo not yet started [info] Starting application demo in the background ... demo Starting demo.Main.main() demo INFO - Ember-Server service bound to address: [::]:8080 ``` -------------------------------- ### GraphQL Query Example: Hero by Episode Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md An example of a GraphQL query to retrieve a hero character based on a specified episode. The query uses the 'hero' field and specifies the 'EMPIRE' episode. ```graphql query { hero(episode: EMPIRE) { name appearsIn } } ``` -------------------------------- ### Translate GraphQL to Query Algebra Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md Example of translating a raw GraphQL query into the initial untyped query algebra term before elaboration occurs. ```scala UntypedSelect("character", None, List(IntBinding("id", 1000)), Nil, UntypedSelect("name", None, Nil, Nil, Empty) ) ``` -------------------------------- ### GraphQL Response Example for Hero Query Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md The expected JSON response for the 'hero' query, showing the name and appearing episodes of the hero character. ```json { "data": { "hero": { "name": "Luke Skywalker", "appearsIn": [ "NEWHOPE", "EMPIRE", "JEDI" ] } } } ``` -------------------------------- ### GraphQL Response Example for Character and Friends Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md The JSON response for the character and friends query, showing the character's name and a list of their friends' names. ```json { "data": { "character": { "name": "Han Solo", "friends": [ { "name": "Luke Skywalker" }, { "name": "Leia Organa" }, { "name": "R2-D2" } ] } } } ``` -------------------------------- ### Define GraphQL HTTP Service with http4s Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md This snippet demonstrates how to define an HTTP service for GraphQL using http4s. It handles request extraction for both GET and POST methods to support query execution. ```scala grackle.docs.Output.snip("demo/src/main/scala/demo/GraphQLService.scala", "#service") ``` -------------------------------- ### GraphQL Response Example for Nested Friends Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md The JSON response for the nested friends query, illustrating the traversal of friendship cycles and returning nested character names. ```json { "data": { "character": { "name": "Luke Skywalker", "friends": [ { "name": "Han Solo", "friends": [ { "name": "Luke Skywalker" }, ... } } } } ``` -------------------------------- ### Create HTTP Routes with http4s for GraphQL Source: https://context7.com/typelevel/grackle/llms.txt Defines a GraphQLService object that generates http4s routes to handle GET and POST requests. It parses GraphQL queries and variables from the request, executes them against a provided mapping, and returns the result. ```scala import cats.effect.{IO, Concurrent} import cats.syntax.all._ import grackle.Mapping import io.circe.{Json, parser} import org.http4s.{HttpRoutes, ParseFailure, QueryParamDecoder} import org.http4s.circe._ import org.http4s.dsl.Http4sDsl object GraphQLService { def mkRoutes[F[_]: Concurrent](prefix: String)(mapping: Mapping[F]): HttpRoutes[F] = { val dsl = new Http4sDsl[F]{} import dsl._ implicit val jsonQPDecoder: QueryParamDecoder[Json] = QueryParamDecoder[String].emap { s => parser.parse(s).leftMap { case parser.ParsingFailure(msg, _) => ParseFailure("Invalid variables", msg) } } object QueryMatcher extends QueryParamDecoderMatcher[String]("query") object OperationNameMatcher extends OptionalQueryParamDecoderMatcher[String]("operationName") object VariablesMatcher extends OptionalValidatingQueryParamDecoderMatcher[Json]("variables") HttpRoutes.of[F] { case GET -> Root / `prefix` :? QueryMatcher(query) +& OperationNameMatcher(op) +& VariablesMatcher(vars0) => vars0.sequence match { case Left(errors) => BadRequest(errors.map(_.sanitized).mkString(",")) case Right(vars) => for { result <- mapping.compileAndRun(query, op, vars) resp <- Ok(result) } yield resp } case req @ POST -> Root / `prefix` => for { body <- req.as[Json] obj <- body.asObject.liftTo[F](InvalidMessageBodyFailure("Invalid GraphQL query")) query <- obj("query").flatMap(_.asString).liftTo[F](InvalidMessageBodyFailure("Missing query field")) op = obj("operationName").flatMap(_.asString) vars = obj("variables") result <- mapping.compileAndRun(query, op, vars) resp <- Ok(result) } yield resp } } } ``` -------------------------------- ### Grackle Schema Definition in Scala Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md Example of defining a GraphQL schema in Scala using Grackle's `schema` string interpolator. This allows for compile-time validation of the schema. ```scala println(grackle.docs.Output.snip("demo/src/main/scala/demo/starwars/StarWarsMapping.scala", "#schema")) ``` -------------------------------- ### Initialize GraphQL Playground with JavaScript Source: https://github.com/typelevel/grackle/blob/main/demo/src/main/resources/assets/playground.html This script listens for the window load event to trigger transition animations and initialize the GraphQLPlayground instance. It extracts the endpoint from URL search parameters, defaulting to 'starwars' if none is provided. ```javascript window.addEventListener('load', function (event) { const loadingWrapper = document.getElementById('loading-wrapper'); loadingWrapper.classList.add('fadeOut'); const root = document.getElementById('root'); root.classList.add('playgroundIn'); const urlParams = new URLSearchParams(window.location.search); const endpoint = urlParams.get('endpoint'); GraphQLPlayground.init(root, { 'endpoint': '/' + (endpoint || 'starwars') }); }); ``` -------------------------------- ### Define Root GraphQL Fields as SQL Objects Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/db-backed-model.md Maps the top-level GraphQL fields to database objects using `SqlObject`. This sets up the entry points for querying data from the database. ```scala val root: SqlObject = SqlObject.query("Query") { SqlObject.field("cities", "city.name", "city.countrycode") } ``` -------------------------------- ### List sbt projects Source: https://github.com/typelevel/grackle/blob/main/CONTRIBUTING.md Displays all available sub-projects within the Grackle build configuration. This is useful for identifying specific modules for targeted testing or building. ```sbt projects ``` -------------------------------- ### Define Loading Screen Styles Source: https://github.com/typelevel/grackle/blob/main/demo/src/main/resources/assets/playground.html CSS rules defining the layout and animation sequences for the loading wrapper and its child elements. It utilizes keyframe animations to handle opacity transitions and stroke-dasharray effects. ```css #loading-wrapper { position: absolute; width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; flex-direction: column; } .logo { width: 75px; height: 75px; margin-bottom: 20px; opacity: 0; animation: fadeIn 0.5s ease-out forwards; } ``` -------------------------------- ### Creating a Database-Backed Mapping with DoobiePgMapping Source: https://context7.com/typelevel/grackle/llms.txt Shows how to implement a GraphQL mapping backed by a PostgreSQL database using Doobie. This includes defining table mappings, SQL columns, and joins between entities. ```scala import cats.effect.{Async, Resource, Sync} import doobie.{Meta, Transactor} import grackle._ import grackle.doobie.postgres.DoobiePgMapping import grackle.syntax._ trait WorldMapping[F[_]] extends DoobiePgMapping[F] { object country extends TableDef("country") { val code = col("code", Meta[String]) val name = col("name", Meta[String]) val continent = col("continent", Meta[String]) val population = col("population", Meta[Int]) val capitalId = col("capital", Meta[Int], nullable = true) } object city extends TableDef("city") { val id = col("id", Meta[Int]) val countrycode = col("countrycode", Meta[String]) val name = col("name", Meta[String]) val population = col("population", Meta[Int]) } val schema = schema""" type Query { country(code: String): Country countries(maxPopulation: Int = -1): [Country!] city(id: Int): City cities(namePattern: String = "%"): [City!] } type Country { name: String! continent: String! population: Int! code: String! cities: [City!]! } type City { id: Int! name: String! country: Country! population: Int! } """ val QueryType = schema.ref("Query") val CountryType = schema.ref("Country") val CityType = schema.ref("City") val typeMappings = TypeMappings( ObjectMapping(QueryType)( SqlObject("country"), SqlObject("countries"), SqlObject("city"), SqlObject("cities") ), ObjectMapping(CountryType)( SqlField("code", country.code, key = true), SqlField("name", country.name), SqlField("continent", country.continent), SqlField("population", country.population), SqlObject("cities", Join(country.code, city.countrycode)) ), ObjectMapping(CityType)( SqlField("id", city.id, key = true), SqlField("countrycode", city.countrycode, hidden = true), SqlField("name", city.name), SqlField("population", city.population), SqlObject("country", Join(city.countrycode, country.code)) ) ) } ``` -------------------------------- ### Run GraphQL Server with http4s IOApp Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md This snippet shows the entry point for a Grackle service using an http4s EmberServer. It integrates the StarWarsMapping and a ResourceService to serve the GraphQL Playground. ```scala object Main extends IOApp { def run(args: List[String]): IO[ExitCode] = { (for { starWarsRoutes <- StarWarsMapping[IO].map(mkRoutes("starwars")) _ <- mkServer(starWarsRoutes) } yield ()).useForever } } ``` ```scala grackle.docs.Output.snip("demo/src/main/scala/demo/DemoServer.scala", "#server") ``` -------------------------------- ### Run a Complete GraphQL Server with EmberServer Source: https://context7.com/typelevel/grackle/llms.txt Demonstrates how to combine multiple GraphQL mappings into a single http4s server application using EmberServer. It includes route composition and server configuration. ```scala import cats.effect.{ExitCode, IO, IOApp, Resource} import cats.syntax.all._ import com.comcast.ip4s._ import org.http4s.HttpRoutes import org.http4s.ember.server.EmberServerBuilder import org.http4s.server.middleware.Logger object Main extends IOApp { def run(args: List[String]): IO[ExitCode] = { (for { starWarsRoutes <- StarWarsMapping[IO].map(GraphQLService.mkRoutes("starwars")) worldRoutes <- WorldMapping[IO].map(GraphQLService.mkRoutes("world")) _ <- mkServer(starWarsRoutes <+> worldRoutes) } yield ()).useForever } def mkServer(routes: HttpRoutes[IO]): Resource[IO, Unit] = { val httpApp = Logger.httpApp(logHeaders = true, logBody = false)(routes.orNotFound) EmberServerBuilder.default[IO] .withHost(ip"0.0.0.0") .withPort(port"8080") .withHttpApp(httpApp) .build.void } } ``` -------------------------------- ### Map GraphQL Types to Database Columns and Joins Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/db-backed-model.md Maps GraphQL types to database tables and columns. It handles nested types by defining SQL joins based on specified conditions, enabling complex data retrieval. ```scala val typeMappings = TypeMappings.empty .add(tables) .add(countries) .add(TypeMappings.Type("City") { Type.Field("name", "city.name") Type.Field("country", Join(countries.code, "city.countrycode")) }) .add(TypeMappings.Type("Country") { Type.Field("code", "country.code") Type.Field("name", "country.name") }) ``` -------------------------------- ### Map Database Tables and Columns for Grackle Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/db-backed-model.md Defines the mapping between database tables and columns for Grackle. It specifies table names, column names, their corresponding doobie `Meta` types, and nullability. ```scala val tables = Table.table("cities") { Table.column("name", "city.name", Meta.String, Nullable) } val countries = Table.table("countries") { Table.column("code", "country.code", Meta.String, NotNullable) :: Table.column("name", "country.name", Meta.String, NotNullable) :: Nil } ``` -------------------------------- ### Elaborate Query Algebra Terms Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md Demonstrates the elaboration step where a specific selector is transformed into a refined, executable predicate-based query structure. ```scala case (QueryType, "character", List(Binding("id", IDValue(id)))) => Elab.transformChild { child => Unique(Filter(Eql(CharacterType / "id", Const(id)), child)) } ``` -------------------------------- ### Creating an In-Memory Mapping with GenericMapping Source: https://context7.com/typelevel/grackle/llms.txt Demonstrates how to use GenericMapping to automatically derive cursor builders for Scala ADTs. This approach is suitable for mapping in-memory data structures to GraphQL schemas. ```scala import cats.MonadThrow import cats.effect.{IO, Resource} import grackle._ import grackle.generic._ import grackle.syntax._ object Episode extends Enumeration { val NEWHOPE, EMPIRE, JEDI = Value } sealed trait Character { def id: String def name: Option[String] def appearsIn: Option[List[Episode.Value]] def friends: Option[List[String]] } case class Human( id: String, name: Option[String], appearsIn: Option[List[Episode.Value]], friends: Option[List[String]], homePlanet: Option[String] ) extends Character case class Droid( id: String, name: Option[String], appearsIn: Option[List[Episode.Value]], friends: Option[List[String]], primaryFunction: Option[String] ) extends Character trait StarWarsMapping[F[_]] extends GenericMapping[F] { import semiauto._ val schema = schema"""...""" val QueryType = schema.ref("Query") val CharacterType = schema.ref("Character") val HumanType = schema.ref("Human") val DroidType = schema.ref("Droid") lazy val characters: List[Character] = List( Human("1000", Some("Luke Skywalker"), Some(List(Episode.NEWHOPE, Episode.EMPIRE)), Some(List("1002", "2001")), Some("Tatooine")), Droid("2001", Some("R2-D2"), Some(List(Episode.NEWHOPE, Episode.EMPIRE)), Some(List("1000")), Some("Astromech")) ) implicit val characterCursor: CursorBuilder[Character] = deriveInterfaceCursorBuilder[Character](CharacterType) implicit val humanCursor: CursorBuilder[Human] = deriveObjectCursorBuilder[Human](HumanType) implicit val droidCursor: CursorBuilder[Droid] = deriveObjectCursorBuilder[Droid](DroidType) val typeMappings = TypeMappings( ObjectMapping(QueryType)( GenericField("hero", characters), GenericField("character", characters), GenericField("human", characters.collect { case h: Human => h }), GenericField("droid", characters.collect { case d: Droid => d }) ) ) } ``` -------------------------------- ### Execute pre-PR validation Source: https://github.com/typelevel/grackle/blob/main/CONTRIBUTING.md Runs a suite of automated checks required for continuous integration. This command ensures code quality and binary compatibility before submitting a pull request. ```sbt prePR ``` -------------------------------- ### CirceMapping for JSON Data Sources in Scala Source: https://context7.com/typelevel/grackle/llms.txt Illustrates how to use CirceMapping to navigate JSON data structures directly within Grackle. It shows static JSON field definition and effectful JSON computation using `RootEffect.computeJson`. ```scala import grackle.circe._ import io.circe.Json import cats.effect.IO abstract class JsonMapping[F[_]] extends CirceMapping[F] { val schema = schema""" type Query { user: User } type User { id: Int! name: String! email: String } """ val QueryType = schema.ref("Query") val UserType = schema.ref("User") val typeMappings = TypeMappings( ObjectMapping(QueryType)( // Static JSON field CirceField("user", Json.obj( "id" -> Json.fromInt(1), "name" -> Json.fromString("Alice"), "email" -> Json.fromString("alice@example.com") )) ) ) } // With effectful JSON computation trait EffectfulJsonMapping[F[_]] extends CirceMapping[F] { val typeMappings = TypeMappings( ObjectMapping(QueryType)( // Compute JSON from an effect RootEffect.computeJson("user") { (path, env) => fetchUserFromApi().map { user => Result.success(Json.obj( "id" -> Json.fromInt(user.id), "name" -> Json.fromString(user.name) )) } } ) ) } ``` -------------------------------- ### Query Algebra Operations in Scala Source: https://context7.com/typelevel/grackle/llms.txt Demonstrates various operations for transforming and combining queries using Grackle's query algebra. These include selecting fields, filtering, ensuring uniqueness, pagination, ordering, counting, narrowing to subtypes, grouping selections, and adding environment data. ```scala import grackle.Query._ // Select a field val selectName = Select("name", None, Empty) val selectWithAlias = Select("name", Some("characterName"), Empty) // Filter results val filtered = Filter(Eql(path / "id", Const("1000")), child) // Get unique result (expects exactly one) val unique = Unique(Filter(Eql(path / "id", Const("1000")), child)) // Limit and offset for pagination val paginated = Limit(10, Offset(20, child)) // Order results val ordered = OrderBy( OrderSelections(List( OrderSelection[Int](CountryType / "population", ascending = false), OrderSelection[String](CountryType / "name", ascending = true) )), child ) // Count elements val counted = Count(Select("cities", Select("name"))) // Narrow to subtype (for interfaces/unions) val narrowed = Narrow(schema.ref("Human"), child) // Group multiple selections val grouped = Group(List( Select("id"), Select("name"), Select("friends", Select("name")) )) // Add environment data val withEnv = Environment(Env("userId" -> "123"), child) ``` -------------------------------- ### Compiling and Running GraphQL Queries with Mapping in Scala Source: https://context7.com/typelevel/grackle/llms.txt The Mapping class in Grackle provides the `compileAndRun` method for executing GraphQL queries and returning JSON results. It supports simple queries, queries with operation names, and queries with variables. ```scala import cats.effect.IO import io.circe.Json // Create a mapping instance val mapping: Mapping[IO] = ??? // Your mapping implementation // Execute a simple query val query = """ query { hero(episode: EMPIRE) { name appearsIn } } """ val result: IO[Json] = mapping.compileAndRun(query) // Returns: {"data":{"hero":{"name":"Luke Skywalker","appearsIn":["NEWHOPE","EMPIRE","JEDI"]}}} // Execute with operation name and variables val queryWithVars = """ query GetCharacter($id: ID!) { character(id: $id) { name friends { name } } } """ val variables = Json.obj("id" -> Json.fromString("1000")) val resultWithVars: IO[Json] = mapping.compileAndRun( queryWithVars, name = Some("GetCharacter"), untypedVars = Some(variables) ) ``` -------------------------------- ### Subscriptions with RootStream in Scala Source: https://context7.com/typelevel/grackle/llms.txt Explains how to implement GraphQL subscriptions using Grackle's `RootStream`. This involves defining a `Subscription` type in the schema and using `RootStream.computeCursor` to yield streams of updates. ```scala import fs2.Stream import grackle._ trait SubscriptionMapping[F[_]] extends Mapping[F] { val schema = schema""" type Query { currentValue: Int! } type Subscription { valueUpdates: Int! } """ val QueryType = schema.ref("Query") val SubscriptionType = schema.ref("Subscription") val typeMappings = TypeMappings( ObjectMapping(QueryType)( CursorField("currentValue", _ => Result.success(42)) ), ObjectMapping(SubscriptionType)( // Stream of cursor updates for subscription RootStream.computeCursor("valueUpdates") { (path, env) => Stream.iterate(0)(_ + 1) .evalMap { n => // Create cursor for each emitted value IO.pure(Result.success(LeafCursor(Context(IntType), n, None, env))) } .metered(1.second) // Emit every second } ) ) } // Execute subscription val subscriptionQuery = "subscription { valueUpdates }" val resultStream: Stream[F, Json] = mapping.compileAndRunSubscription(subscriptionQuery) ``` -------------------------------- ### Define Query Elaborator for Database Model Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/db-backed-model.md Defines an elaborator to transform GraphQL query algebra terms into a form suitable for translation into SQL queries. This is crucial for executing queries against the database. ```scala val elaborator: Query ~> λ[α => ConnectionIO[α]] = QueryCompiler.elaborator(schema, root, typeMappings) .withRelsByUnique(Query.rel("country", "city.countrycode", countries.code)) .withRelsByUnique(Query.rel("cities", "country.code", "city.countrycode")) ``` -------------------------------- ### Add Grackle dependencies to build.sbt Source: https://github.com/typelevel/grackle/blob/main/README.md Configuration for adding Grackle core and optional backend modules to a Scala project. These dependencies enable support for various data sources including Circe, Shapeless, and SQL databases via Doobie or Skunk. ```scala // Required: Scala 2.13/3.3+ libraryDependencies += "org.typelevel" %% "grackle-core" % "0.26.0" // Optional: support for in-memory Json backend using circe libraryDependencies += "org.typelevel" %% "grackle-circe" % "0.26.0" // Optional: support for in-memory generic Scala backend using shapeless libraryDependencies += "org.typelevel" %% "grackle-generic" % "0.26.0" // Optional: support for Postgres backend via Doobie (JVM only) libraryDependencies += "org.typelevel" %% "grackle-doobie-pg" % "0.26.0" // Optional: support for Postgres backend via Skunk libraryDependencies += "org.typelevel" %% "grackle-skunk" % "0.26.0" // Optional: support for Oracle backend via Doobie (JVM only) libraryDependencies += "org.typelevel" %% "grackle-doobie-oracle" % "0.26.0" // Optional: support for SQL Server backend via Doobie (JVM only) libraryDependencies += "org.typelevel" %% "grackle-doobie-mssql" % "0.26.0" ``` -------------------------------- ### Define GraphQL Schema using Scala String Interpolator Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/db-backed-model.md Defines the GraphQL schema as a Scala value using the `schema` string interpolator. This allows for compile-time validation of the GraphQL schema. ```scala schema """ type Query { cities(namePattern: String): [City] } type City { name: String country: Country } type Country { code: String name: String } """ ``` -------------------------------- ### Apply Predicates for Query Filtering Source: https://context7.com/typelevel/grackle/llms.txt Shows various ways to filter query results in Grackle using predicates such as equality, range comparisons, pattern matching, logical combinations, and null checks. ```scala import grackle.Predicate._ import grackle.Query._ val byId = Filter(Eql(CharacterType / "id", Const("1000")), child) val byMaxPop = Filter(LtEql(CountryType / "population", Const(1000000)), child) val byMinPop = Filter(Gt(CountryType / "population", Const(100000)), child) val byPattern = Filter(Like(CityType / "name", "New%", caseSensitive = true), child) val combined = Filter( And( Eql(CountryType / "continent", Const("Europe")), LtEql(CountryType / "population", Const(10000000)) ), child ) val hasCapital = Filter(IsNull(CountryType / "capitalId", isNull = false), child) val inContinents = Filter( In(CountryType / "continent", List("Europe", "Asia", "Africa")), child ) val startsWithNew = Filter(StartsWith(CityType / "name", "New"), child) val matchesRegex = Filter(Matches(CityType / "name", "^[A-Z].*".r), child) ``` -------------------------------- ### Mapping Validation in Scala Source: https://context7.com/typelevel/grackle/llms.txt Details Grackle's mapping validation capabilities, which help catch configuration errors at startup. It covers validating mappings, throwing exceptions for errors, and validating into effect types, along with common validation failure types. ```scala import grackle.ValidationFailure.Severity // Validate mapping, returns list of problems val problems: List[ValidationFailure] = mapping.validate(Severity.Warning) // Validate and throw exception if problems found mapping.unsafeValidate(Severity.Warning) // Validate into an effect type val validated: IO[Unit] = mapping.validateInto[IO](Severity.Warning) // TypeMappings also supports validation val typeMappings = TypeMappings( // ... mappings ... ) // Check for common issues: // - MissingTypeMapping: GraphQL type has no corresponding mapping // - MissingFieldMapping: Object mapping doesn't include a required field // - UnusedTypeMapping: Mapping defined but never used // - UnusedFieldMapping: Field mapping defined but never used ``` -------------------------------- ### Scala Model Values and Friend Resolution Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md Illustrates the Scala data structure for the Star Wars model, including how friends are identified by IDs and resolved using the `resolveFriends` method to handle cycles. ```scala println(grackle.docs.Output.snip("demo/src/main/scala/demo/starwars/StarWarsMapping.scala", "#model_values")) ``` -------------------------------- ### GraphQL Schema Definition Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md The GraphQL schema defining the types, queries, and enums for the Star Wars API. It includes types for Query, Episode, Character, Droid, and Human. ```graphql type Query { hero(episode: Episode!): Character character(id: ID!): Character human(id: ID!): Human droid(id: ID!): Droid } enum Episode { NEWHOPE EMPIRE JEDI } interface Character { id: ID! name: String! friends: [Character] appearsIn: [Episode]! } type Droid implements Character { id: ID! name: String! friends: [Character] appearsIn: [Episode]! primaryFunction: String } type Human implements Character { id: ID! name: String! friends: [Character] appearsIn: [Episode]! homePlanet: String } ``` -------------------------------- ### Query Elaboration with SelectElaborator in Scala Source: https://context7.com/typelevel/grackle/llms.txt SelectElaborator transforms GraphQL query arguments into query algebra operations like Filter, Unique, Limit, and OrderBy. It handles various query patterns, including filtering by country code, complex filtering, ordering, and pagination for countries, and filtering cities by ID or name pattern. ```scala import grackle._ import grackle.Predicate._ import grackle.Query._ import grackle.QueryCompiler._ import grackle.Value._ override val selectElaborator = SelectElaborator { // Transform country(code: "US") into a unique filtered query case (QueryType, "country", List(Binding("code", StringValue(code)))) => Elab.transformChild { child => Unique(Filter(Eql(CountryType / "code", Const(code)), child)) } // Transform countries with filtering, ordering, and pagination case (QueryType, "countries", List( Binding("maxPopulation", IntValue(max)), Binding("sortByPopulation", BooleanValue(sortByPop)), Binding("offset", IntValue(off)), Binding("limit", IntValue(lim)) ) ) => def filter(query: Query): Query = if (max < 0) query else Filter(LtEql(CountryType / "population", Const(max)), query) def order(query: Query): Query = if (!sortByPop) query else OrderBy( OrderSelections(List(OrderSelection[Int](CountryType / "population"))), query ) def offset(query: Query): Query = if (off < 1) query else Offset(off, query) def limit(query: Query): Query = if (lim < 0) query else Limit(lim, query) Elab.transformChild(child => limit(offset(order(filter(child))))) // Transform city(id: 123) query case (QueryType, "city", List(Binding("id", IntValue(id)))) => Elab.transformChild(child => Unique(Filter(Eql(CityType / "id", Const(id)), child)) ) // Transform cities with pattern matching using Like predicate case (QueryType, "cities", List(Binding("namePattern", StringValue(pattern)))) => if (pattern == "%" ) Elab.unit else Elab.transformChild { Filter(Like(CityType / "name", pattern, caseSensitive = true), child) } } ``` -------------------------------- ### Define GraphQL Schema with `schema` String Interpolator Source: https://context7.com/typelevel/grackle/llms.txt Defines a GraphQL schema using Grackle's `schema` string interpolator, which validates the schema at compile time. It includes types for queries, characters, humans, droids, and episodes. ```scala import grackle._ import grackle.syntax._ val schema = schema""" type Query { hero(episode: Episode!): Character! character(id: ID!): Character human(id: ID!): Human droid(id: ID!): Droid } enum Episode { NEWHOPE EMPIRE JEDI } interface Character { id: String! name: String friends: [Character!] appearsIn: [Episode!] } type Human implements Character { id: String! name: String friends: [Character!] appearsIn: [Episode!] homePlanet: String } type Droid implements Character { id: String! name: String friends: [Character!] appearsIn: [Episode!] primaryFunction: String } """ ``` -------------------------------- ### Define Grackle Query Algebra ADT Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md The core data structures representing the query algebra in Grackle. These case classes and objects define the operations available for query transformation and execution. ```scala case class UntypedSelect( name: String, alias: Option[String], args: List[Binding], directives: List[Directive], child: Query ) case class Select(name: String, alias: Option[String], child: Query) case class Group(queries: List[Query]) case class Unique(child: Query) case class Filter(pred: Predicate, child: Query) case class Introspect(schema: Schema, child: Query) case class Environment(env: Env, child: Query) case class Narrow(subtpe: TypeRef, child: Query) case class Limit(num: Int, child: Query) case class Offset(num: Int, child: Query) case class OrderBy(selections: OrderSelections, child: Query) case class Count(child: Query) case class TransformCursor(f: Cursor => Result[Cursor], child: Query) case class Component[F[_]](mapping: Mapping[F], ...) case class Effect[F[_]](handler: EffectHandler[F], child: Query) case object Empty ``` -------------------------------- ### Scala Data Model Types for Star Wars API Source: https://github.com/typelevel/grackle/blob/main/docs/tutorial/in-memory-model.md Defines the ordinary Scala data types used to back the Star Wars API. These types have no Grackle dependencies and capture the required information. ```scala println(grackle.docs.Output.snip("demo/src/main/scala/demo/starwars/StarWarsMapping.scala", "#model_types")) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.