{"id":14975989,"url":"https://github.com/jarlakxen/drunk","last_synced_at":"2025-07-06T21:02:54.410Z","repository":{"id":48562096,"uuid":"118179491","full_name":"Jarlakxen/drunk","owner":"Jarlakxen","description":"A simple GraphQL client on top of Sangria, Akka HTTP and Circe.","archived":false,"fork":false,"pushed_at":"2023-10-06T22:35:57.000Z","size":42,"stargazers_count":62,"open_issues_count":6,"forks_count":21,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-11T13:03:21.082Z","etag":null,"topics":["akka-http","circe","graphql","graphql-client","sangria","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jarlakxen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-19T21:17:16.000Z","updated_at":"2024-08-15T19:36:59.000Z","dependencies_parsed_at":"2024-09-18T18:42:50.908Z","dependency_job_id":null,"html_url":"https://github.com/Jarlakxen/drunk","commit_stats":{"total_commits":27,"total_committers":4,"mean_commits":6.75,"dds":"0.14814814814814814","last_synced_commit":"ddbb314b94a1f8cba5ad3a725c0b638088c788ff"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jarlakxen%2Fdrunk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jarlakxen%2Fdrunk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jarlakxen%2Fdrunk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jarlakxen%2Fdrunk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jarlakxen","download_url":"https://codeload.github.com/Jarlakxen/drunk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219860932,"owners_count":16556009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["akka-http","circe","graphql","graphql-client","sangria","scala"],"created_at":"2024-09-24T13:53:05.894Z","updated_at":"2024-10-11T13:03:28.295Z","avatar_url":"https://github.com/Jarlakxen.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Drunk\n\nA simple GraphQL client on top of [Sangria](http://sangria-graphql.org/), [Akka HTTP](https://doc.akka.io/docs/akka-http/current/) and [Circe](https://circe.github.io/circe/).\n\n\n## Quickstart\n\nAdd the following dependency:\n\n```scala\n  resolvers += Resolver.bintrayRepo(\"jarlakxen\", \"maven\")\n\n  \"com.github.jarlakxen\" %% \"drunk\" % \"2.5.0\"\n```\n\nThen, import:\n\n\n```scala\n  import com.github.jarlakxen.drunk._\n  import io.circe._, io.circe.generic.semiauto._\n  import sangria.macros._\n```\n\nThere are three ways to create a `GraphQLClient`:\n\n1) As Akka Https flow connection\n\n```\n import akka.http.scaladsl.model.Uri\n \n val uri: Uri = Uri(s\"https://$host:$port/api/graphql\")\n\n val http: HttpExt = Http()\n val flow: Flow[HttpRequest, HttpResponse, Future[OutgoingConnection]] = http.outgoingConnectionHttps(uri.authority.host.address(), uri.effectivePort)\n val client = GraphQLClient(uri, flow, clientOptions = ClientOptions.Default, headers = Nil)\n\n```\n\n2) As Akka Http flow connection\n\n```\n import akka.http.scaladsl.model.Uri\n \n val uri: Uri = Uri(s\"http://$host:$port/api/graphql\")\n\n val http: HttpExt = Http()\n val flow: Flow[HttpRequest, HttpResponse, Future[OutgoingConnection]] = http.outgoingConnection(uri.authority.host.address(), uri.effectivePort)\n val client = GraphQLClient(uri, flow, clientOptions = ClientOptions.Default, headers = Nil)\n\n```\n\n3) As Akka Http single request\n\n```  \n  val client = GraphQLClient(s\"http://$host:$port/api/graphql\")\n```\n\nThen, query:\n\n```\n  val query =\n    graphql\"\"\"\n      query HeroAndFriends {\n        hero {\n          id\n          name\n          friends {\n            name\n          }\n          appearsIn\n        }\n      }\n    \"\"\"\n      \n  val cursor: GraphQLCursor = client.query[HeroQuery](query)\n  val data: Future[GraphQLResponse[HeroQuery]] = cursor.result\n```\n\n#### Working with the `GraphQLCursor`\n\n```scala\n\n  type HerosQuery = Map[String, List[Hero]]\n  \n  case class Pagination(offset: Int, size: Int)\n\n  val query =\n    graphql\"\"\"\n      query Heros($offset: Int, $size: Int) {\n        heros(offset: $offset, size: $size) {\n          id\n          name\n          friends {\n            name\n          }\n          appearsIn\n        }\n      }\n    \"\"\"\n      \n  val page1: GraphQLCursor[HerosQuery, Pagination] = \n    client.query(query, Pagination(0, 10))\n  val page2: GraphQLCursor[HerosQuery, Pagination] = \n    page1.fetchMore(lastPage =\u003e lastPage.copy(offset = lastPage.offset + lastPage.size ) )\n```\n\n### Mutations\n\n```scala\n  import com.github.jarlakxen.drunk._\n  import io.circe._, io.circe.generic.semiauto._\n  import sangria.macros._\n\n  case class User(id: String, name: String)\n  \n  val client = GraphQLClient(s\"http://$host:$port/api/graphql\")\n\n  val mutation =\n    graphql\"\"\"\n      mutation($user1: String!, $user2: String!) {\n        user1: newUser(name: $user1) {\n          id\n          name\n        }\n        user2: newUser(name: $user2) {\n          id\n          name\n        }\n      }\n    \"\"\"\n    val result: Future[GraphQLResponse[Map[String, User]]] = \n      client.query(mutation, Map(\"user1\" -\u003e \"123\", \"user2\" -\u003e \"456\"))\n```\n\n### Schema Introspection\n\n```scala\n  import com.github.jarlakxen.drunk._\n  import sangria.introspection.IntrospectionSchema\n\n  val client = GraphQLClient(s\"http://$host:$port/api/graphql\")\n      \n  val result: Future[GraphQLResponse[IntrospectionSchema]] = client.schema\n```\n\n## Typename Derive\n\nIt's very common in GraphQL to have response with polymorphic objects in the responses. One way to discriminate the type of object is to check the `__typename` field. For that purpose there an special derive decoder in `com.github.jarlakxen.drunk.circe._`:\n\n```scala\n  import com.github.jarlakxen.drunk.circe._\n  import io.circe._, io.circe.generic.semiauto._\n\n  trait Character {\n    def id: String\n    def name: Option[String]\n    def friends: List[String]\n    def appearsIn: List[Episode.Value]\n  }\n  \n  case class Human(\n    id: String,\n    name: Option[String],\n    friends: List[String],\n    appearsIn: List[Episode.Value],\n    homePlanet: Option[String]) extends Character\n  \n  case class Droid(\n    id: String,\n    name: Option[String],\n    friends: List[String],\n    appearsIn: List[Episode.Value],\n    primaryFunction: Option[String]) extends Character\n    \n  implicit val humanDecoder: Decoder[Human] = deriveDecoder\n  implicit val droidDecoder: Decoder[Droid] = deriveDecoder\n  \n  implicit val characterDecoder: Decoder[Character] = deriveByTypenameDecoder(\n    \"Human\".decodeAs[Human], // for __typename: 'Human' is going to use humanDecoder\n    \"Droid\".decodeAs[Droid] // for __typename: 'Droid' is going to use droidDecoder\n  )\n```\n\nThis code can be use to parse a response like:\n\n\n```json\n{\n  \"__typename\": \"Droid\"\n  \"name\": \"R2D2\"\n  ....\n}\n```\n\n\u003e Take into account the client automatically adds the '__typename' field to every selector, so it's not required to be added in the queries.\n\n\n## Extensions\n\nThere are several extension for GraphQL, this client supports:\n\n* [Apollo cache control](https://github.com/apollographql/apollo-cache-control)\n* [sangria-slowlog](http://sangria-graphql.org/learn/#profiling-graphql-query-execution)\n\n\nTo get the information of the extensions you can:\n\n```scala     \n  val cursor: GraphQLCursor = client.query[HeroQuery](query)\n  val extensions: Future[GraphQLExtensions] = cursor.extensions\n  val metrics: Future[Option[GraphQLMetricsExtension]] = extensions.map(_.metrics)\n  val cacheControl: Future[Option[GraphQLCacheControlExtension]] = extensions.map(_.cacheControl)\n```\n\n## Contributing\n\nIf you have a question, or hit a problem, feel free to ask in the [issues](https://github.com/jarlakxen/drunk/issues)!\n\nOr, if you encounter a bug, something is unclear in the code or documentation, don’t hesitate and open an issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjarlakxen%2Fdrunk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjarlakxen%2Fdrunk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjarlakxen%2Fdrunk/lists"}