[
  {
    "path": ".gitignore",
    "content": "# ensime\n*.*~\n.ensime\n.ensime_cache\nproject/ensime-plugin.sbt\n\n# sbt\ntarget/\nproject/target/\nproject/project/"
  },
  {
    "path": ".travis.yml",
    "content": "language: scala\n\nscala:\n  - 2.11.11\n  - 2.12.3\n\njdk:\n  - oraclejdk8\n\nscript:\n  - sbt ++$TRAVIS_SCALA_VERSION clean test\n  - sbt \"project sharedJS\" \"fastOptJS\"\n  - sbt \"project js-client\" \"fastOptJS\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "### 0.2.0\n - `StatusCodes` and `MediaTypes` are in distinct `object`s, thus, have to be imported explicitly\n - improved Ammonite integration\n - internal: separated decoded and raw requests with `RawApiRequest` and `ApiRequest`\n - fixed `implicitNotFound` message for `ApiRequest`\n - implemented [#31](https://github.com/pheymann/typedapi/issues/31) [#35](https://github.com/pheymann/typedapi/issues/35) [#36](https://github.com/pheymann/typedapi/issues/36)\n - server endpoints have to define a response code:\n ```Scala\n derive[IO](Api) { input =>\n   success(/*...*/)\n      ^\n }\n ```\n \n\n### 0.1.0\n - internal cleanups and refactorings\n - extended example project and added ScalaJS client\n - centralized http-support specs\n - added akka-http support on server and client-side\n - added scalaj-http support on the client-side\n - added ScalaJS compilation support for shared and client code\n - implemented basic ScalaJS client\n - added body encoding types and made them mandatory (several hundred Mediatypes supported)\n   ```Scala\n   := :> ReqBody[Json, User] :> Get[Json, User]\n    _______________^__________________^\n   ```\n \n - `RawHeaders` was removed\n - fixed headers were added; a fixed header is a statically known key-value pair, therefore, no input is required\n   ```Scala\n   // dsl\n   := :> Header(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]\n   \n   // function\n   api(Get[Json, User], headers = Headers add(\"Access-Control-Allow-Origin\", \"*\"))\n   ```\n   \n - changes to the server API:\n   - `NoReqBodyExecutor` and `ReqBodyExecutor` now expect a `MethodType`:\n   ```Scala\n   new NoReqBodyExecutor[El, KIn, VIn, M, F, FOut] {\n   ____________________________________^\n  \n   new ReqBodyExecutor[El, KIn, VIn, Bd, M, ROut, POut, F, FOut] {\n   ______________________________________^\n   ```\n   \n   - fixed header only sent by the server\n   ```Scala\n   := :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]\n   \n   api(Get[Json, User], Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\"))\n   ```\n   - extract headers which have keys that match a `String`\n   ```Scala\n   := :> Server.Match[String](\"Control\") :> Get[Json, User]\n   \n   api(Get[Json, User], Headers.serverMatch[String](\"Control\"))\n   ```\n - changes to the client API:\n   - new encoding types add `Content-Type` and `Accept` headers\n   - fixed header only sent by the client\n   ```Scala\n   := :> Client.Header(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]\n   \n   api(Get[Json, User], Headers.client(\"Access-Control-Allow-Origin\", \"*\"))\n   ```\n   - send dynamic header ignore it on the server-side\n   ```Scala\n   := :> Client.Header[String](\"Foo\") :> Get[Json, User]\n   \n   api(Get[Json, User], Headers.client[String](\"Foo\"))\n   ```\n\n### 0.1.0-RC5 / Almost there\n - changes to the client API:\n ```Scala\n val ApiList =\n   (:= :> Get[Foo]) :|:\n   (:= :> RequestBody[Foo] :> Put[Foo])\n   \n // `:|:` removed for API compositions\n val (get, put) = deriveAll(ApiList)\n ```\n \n - changes to the server API:\n ```Scala\n // same for endpoint compositions\n val e = deriveAll[IO](ApiList).from(get, put)\n ```\n\n### 0.1.0-RC4 / Towards a stable API\n - changes to the client API:\n ```Scala\n val Api     = := :> Get[Foo]\n val ApiList =\n   (:= :> Get[Foo]) :|:\n   (:= :> RequestBody[Foo] :> Put[Foo])\n \n // not `compile`, but\n val foo = derive(Api)\n \n val (foo2 :|: bar :|: =:) = deriveAll(ApiList)\n \n ...\n // explicitly pass ClientManager\n foo().run[IO](cm)\n _______________^\n ```\n \n - changes to the server API\n ```Scala\n // not `link.to`, but\n val endpoint = derive[IO](Api).from(...)\n \n val endpoints = deriveAll[IO](ApiList).from(...)\n ```\n \n - major changes were applied to the internal code to reach a stable state (see [this PR](https://github.com/pheymann/typedapi/pull/13))\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Paul Heymann\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![Build Status](https://travis-ci.org/pheymann/typedapi.svg?branch=master)](https://travis-ci.org/pheymann/typedapi)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.pheymann/typedapi-client_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.pheymann/typedapi-shared_2.12)\n[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pheymann/Lobby)\n[![Scala.js](https://www.scala-js.org/assets/badges/scalajs-0.6.17.svg)](https://www.scala-js.org/)\n\n*experimental project*: see issues [#39](https://github.com/pheymann/typedapi/issues/39) and [#41](https://github.com/pheymann/typedapi/issues/41)\n\n# Typedapi\nDefine type safe APIs and let the Scala compiler do the rest:\n\n### Api definition\n```Scala\nimport typedapi._\n\nval MyApi =\n  // GET {body: User} /fetch/user?{name: String}\n  api(method = Get[MT.`application/json`, User], \n      path = Root / \"fetch\" / \"user\", \n      queries = Queries add Query[String]('name)) :|:\n  // POST {body: User} /create/user\n  apiWithBody(method = Post[MT.`application/json`, User], \n              body = ReqBody[Json, User], \n              path = Root / \"create\" / \"user\")\n```\n\nAnd for the Servant lovers:\n\n```Scala\nimport typedapi.dsl._\n\nval MyApi = \n  // GET {body: User} /fetch/user?{name: String}\n  (:= :> \"fetch\" :> \"user\" :> Query[String]('name) :> Get[MT.`application/json`, User]) :|:\n  // POST {body: User} /create/user\n  (:= :> \"create\" :> \"user\" :> ReqBody[Json, User] :> Post[MT.`application/json`, User])\n```\n\n### Client side\n```Scala\nimport typedapi.client._\n\nval (fetch, create) = deriveAll(MyApi)\n\nimport typedapi.client.http4s._; import cats.effect.IO; import org.http4s.client.blaze.Http1Client\n\nval cm = ClientManager(Http1Client[IO]().unsafeRunSync, \"http://my-host\", 8080)\n\nfetch(\"joe\").run[IO](cm): IO[User]\n```\n\n### Server side\n```Scala\nimport typedapi.server._\n\nval fetch: String => IO[Result[User]] = name => findUserIO(name).map(success)\nval create: User => IO[Result[User]] = user => createUserIO(user).map(success)\n\nval endpoints = deriveAll[IO](MyApi).from(fetch, create)\n\nimport typedapi.server.http4s._; import cats.effect.IO; import org.http4s.server.blaze.BlazeBuilder\n\nval sm     = ServerManager(BlazeBuilder[IO], \"http://my-host\", 8080)\nval server = mount(sm, endpoints)\n\nserver.unsafeRunSync()\n```\n\nThis is all you have to do to define an API with multiple endpoints and to create a working client and server for them.\n\nYou can find the above code as a complete project [here](https://github.com/pheymann/typedapi/tree/master/docs/example).\n\n## Motivation\nThis library is the result of the following questions:\n\n> How much can we encode on the type level? Are we able to describe a whole API and generate the call functions from that without using Macros?\n\nIt is inspired by [Servant](https://github.com/haskell-servant/servant) and it provides an API layer which is independent of the underlying server/client implementation. Right now Typedapi supports:\n\n  - [http4s](https://github.com/http4s/http4s)\n  - [akka-http](https://github.com/akka/akka-http)\n  - [scalaj-http](https://github.com/scalaj/scalaj-http) on the client-side\n  - ScalaJS on the client-side\n\nIf you need something else take a look at this [doc](https://github.com/pheymann/typedapi/blob/master/docs/ExtendIt.md#write-your-own-client-backend).\n\n## Get this library\nIt is available for Scala 2.11, 2.12 and ScalaJS and can be downloaded as Maven artifact:\n\n```\n// dsl\n\"com.github.pheymann\" %% \"typedapi-client\" % <version>\n\"com.github.pheymann\" %% \"typedapi-server\" % <version>\n\n// http4s support\n\"com.github.pheymann\" %% \"typedapi-http4s-client\" % <version>\n\"com.github.pheymann\" %% \"typedapi-http4s-server\" % <version>\n\n// akka-http support\n\"com.github.pheymann\" %% \"typedapi-akka-http-client\" % <version>\n\"com.github.pheymann\" %% \"typedapi-akka-http-server\" % <version>\n\n// Scalaj-Http client support\n\"com.github.pheymann\" %% \"typedapi-scalaj-http-client\" % <version>\n\n// ScalaJS client support\n\"com.github.pheymann\" %% \"typedapi-js-client\" % <version>\n```\n\nYou can also build it on your machine:\n\n```\ngit clone https://github.com/pheymann/typedapi.git\ncd typedapi\nsbt \"+ publishLocal\"\n```\n\n## Ammonite\nTypedapi also offers an improved experience for [Ammonite](http://ammonite.io/#Ammonite-REPL) and [ScalaScripts](http://ammonite.io/#ScalaScripts):\n\n```Scala\nimport $ivy.`com.github.pheymann::typedapi-ammonite-client:<version>`\n\nimport typedapi._\nimport client._\nimport amm._\n\nval Readme = api(Get[MT.`text/html`, String], Root / \"pheymann\" / \"typedapi\" / \"master\" / \"README.md\")\nval readme = derive(Readme)\n\n// gives you the raw scalaj-http response\nval cm = clientManager(\"https://raw.githubusercontent.com\")\nval response = get().run[Id].raw(cm)\n\nresponse.body\nresponse.headers\n...\n```\n\nIn case Ammonite cannot resolve `com.dwijnand:sbt-compat:1.0.0`, follow [this](https://github.com/pheymann/typedapi/blob/master/docs/ClientCreation.md#ammonite) solution.\n\n## Documentation\nThe documentation is located in [docs](https://github.com/pheymann/typedapi/blob/master/docs) and covers the following topics so far:\n - [How to define an API](https://github.com/pheymann/typedapi/blob/master/docs/ApiDefinition.md)\n - [How to create a client](https://github.com/pheymann/typedapi/blob/master/docs/ClientCreation.md)\n - [How to create a server](https://github.com/pheymann/typedapi/blob/master/docs/ServerCreation.md)\n - [Extend the library](https://github.com/pheymann/typedapi/blob/master/docs/ExtendIt.md)\n - Typelevel Summit 2018 Berlin Talk [Typedapi: Define your API on the type-level](https://github.com/pheymann/typelevel-summit-2018)\n - and a [post](https://typelevel.org/blog/2018/06/15/typedapi.html) on the Typelevel Blog describing the basic concept behind this library.\n\n## Dependencies\n - [shapeless 2.3.3](https://github.com/milessabin/shapeless/)\n\n## Contribution\nContributions are highly appreciated. If you find a bug or you are missing the support for a specific client/server library consider opening a PR with your solution.\n"
  },
  {
    "path": "akka-http-client/src/main/scala/typedapi/client/akkahttp/package.scala",
    "content": "package typedapi.client\n\nimport akka.http.scaladsl.HttpExt\nimport akka.http.scaladsl.model.RequestEntity\nimport akka.http.scaladsl.model.headers.RawHeader\nimport akka.http.scaladsl.model.{ HttpMethods, HttpRequest, HttpResponse, Uri }\nimport akka.http.scaladsl.unmarshalling.{Unmarshal, FromEntityUnmarshaller}\nimport akka.http.scaladsl.marshalling.{Marshal, ToEntityMarshaller}\nimport akka.stream.Materializer\n\nimport scala.concurrent.duration.FiniteDuration\nimport scala.concurrent.{ ExecutionContext, Future }\n\npackage object akkahttp {\n\n  private def mkRequest(uri: String, queries: Map[String, List[String]], headers: Map[String, String]): HttpRequest =\n    HttpRequest(\n        uri = Uri(uri).withQuery(Uri.Query(queries.mapValues(_.mkString(\",\")))),\n        headers = headers.map { case (key, value) => RawHeader(key, value) }(collection.breakOut)\n      )\n\n  private def execRequest(client: HttpExt, request: HttpRequest, bodyConsumerTimeout: FiniteDuration)\n                         (implicit ec: ExecutionContext, \n                                   mat: Materializer): Future[HttpResponse] =\n    client.singleRequest(request)\n      .flatMap { response =>\n        response.toStrict(bodyConsumerTimeout)\n      }\n\n  def rawGetRequest(bodyConsumerTimeout: FiniteDuration)(implicit ec: ExecutionContext, \n                                                                  mat: Materializer) = new RawGetRequest[HttpExt, Future] {\n    type Resp = HttpResponse\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[Resp] = {\n      val request = mkRequest(deriveUriString(cm, uri), queries, headers).copy(HttpMethods.GET)\n\n      execRequest(cm.client, request, bodyConsumerTimeout)\n    }\n  }\n\n  implicit def rawGetRequestImpl(implicit bodyConsumerTimeout: FiniteDuration,\n                                          ec: ExecutionContext,\n                                          mat: Materializer): RawGetRequest[HttpExt, Future] = rawGetRequest(bodyConsumerTimeout)\n\n  def getRequest[A](bodyConsumerTimeout: FiniteDuration)(implicit decoder: FromEntityUnmarshaller[A],\n                                                                  ec: ExecutionContext, \n                                                                  mat: Materializer) = new GetRequest[HttpExt, Future, A] {\n    private val raw = rawGetRequest(bodyConsumerTimeout)\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap { response =>\n        Unmarshal(response.entity).to[A]\n      }\n  }\n\n  implicit def getRequestImpl[A](implicit bodyConsumerTimeout: FiniteDuration,\n                                          decoder: FromEntityUnmarshaller[A],\n                                          ec: ExecutionContext,\n                                          mat: Materializer): GetRequest[HttpExt, Future, A] = getRequest(bodyConsumerTimeout)\n\n  def rawPutRequest(bodyConsumerTimeout: FiniteDuration)(implicit ec: ExecutionContext, \n                                                                  mat: Materializer) = new RawPutRequest[HttpExt, Future] {\n    type Resp = HttpResponse\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[Resp] = {\n      val request = mkRequest(deriveUriString(cm, uri), queries, headers).copy(HttpMethods.PUT)\n\n      execRequest(cm.client, request, bodyConsumerTimeout)\n    }\n  }\n\n  implicit def rawPutRequestImpl(implicit bodyConsumerTimeout: FiniteDuration,\n                                          ec: ExecutionContext,\n                                          mat: Materializer): RawPutRequest[HttpExt, Future] = rawPutRequest(bodyConsumerTimeout)\n\n  def putRequest[A](bodyConsumerTimeout: FiniteDuration)(implicit decoder: FromEntityUnmarshaller[A],\n                                                                  ec: ExecutionContext, \n                                                                  mat: Materializer) = new PutRequest[HttpExt, Future, A] {\n    private val raw = rawPutRequest(bodyConsumerTimeout)\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap { response =>\n        Unmarshal(response.entity).to[A]\n      }\n  }\n\n  implicit def putRequestImpl[A](implicit bodyConsumerTimeout: FiniteDuration,\n                                          decoder: FromEntityUnmarshaller[A],\n                                          ec: ExecutionContext,\n                                          mat: Materializer): PutRequest[HttpExt, Future, A] = putRequest(bodyConsumerTimeout)\n\n  def rawPutBodyRequest[Bd](bodyConsumerTimeout: FiniteDuration)(implicit encoder: ToEntityMarshaller[Bd],\n                                                                          ec: ExecutionContext, \n                                                                          mat: Materializer) = new RawPutWithBodyRequest[HttpExt, Future, Bd] {\n    type Resp = HttpResponse\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[HttpExt]): Future[Resp] = {\n      Marshal(body).to[RequestEntity].flatMap { marshalledBody =>\n        val request = mkRequest(deriveUriString(cm, uri), queries, headers - \"Content-Type\").copy(HttpMethods.PUT, entity = marshalledBody)\n\n        execRequest(cm.client, request, bodyConsumerTimeout)\n      }\n    }\n  }\n\n  implicit def rawPutBodyRequestImpl[Bd](implicit bodyConsumerTimeout: FiniteDuration,\n                                                  encoder: ToEntityMarshaller[Bd],\n                                                  ec: ExecutionContext,\n                                                  mat: Materializer): RawPutWithBodyRequest[HttpExt, Future, Bd] = rawPutBodyRequest(bodyConsumerTimeout)\n\n  def putBodyRequest[Bd, A](bodyConsumerTimeout: FiniteDuration)(implicit encoder: ToEntityMarshaller[Bd],\n                                                                          decoder: FromEntityUnmarshaller[A],\n                                                                          ec: ExecutionContext, \n                                                                          mat: Materializer) = new PutWithBodyRequest[HttpExt, Future, Bd, A] {\n    private val raw = rawPutBodyRequest(bodyConsumerTimeout)\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[HttpExt]): Future[A] =\n      raw(uri, queries, headers, body, cm).flatMap { response =>\n        Unmarshal(response.entity).to[A]\n      }\n  }\n\n  implicit def putBodyRequestImpl[Bd, A](implicit bodyConsumerTimeout: FiniteDuration,\n                                                  encoder: ToEntityMarshaller[Bd],\n                                                  decoder: FromEntityUnmarshaller[A],\n                                                  ec: ExecutionContext,\n                                                  mat: Materializer): PutWithBodyRequest[HttpExt, Future, Bd, A] = putBodyRequest(bodyConsumerTimeout)\n\n  def rawPostRequest(bodyConsumerTimeout: FiniteDuration)(implicit ec: ExecutionContext, \n                                                                   mat: Materializer) = new RawPostRequest[HttpExt, Future] {\n    type Resp = HttpResponse\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[Resp] = {\n      val request = mkRequest(deriveUriString(cm, uri), queries, headers).copy(HttpMethods.POST)\n\n      execRequest(cm.client, request, bodyConsumerTimeout)\n    }\n  }\n\n  implicit def rawPostRequestImpl(implicit bodyConsumerTimeout: FiniteDuration,\n                                           ec: ExecutionContext,\n                                           mat: Materializer): RawPostRequest[HttpExt, Future] = rawPostRequest(bodyConsumerTimeout)\n\n  def postRequest[A](bodyConsumerTimeout: FiniteDuration)(implicit decoder: FromEntityUnmarshaller[A],\n                                                                   ec: ExecutionContext, \n                                                                   mat: Materializer) = new PostRequest[HttpExt, Future, A] {\n    private val raw = rawPostRequest(bodyConsumerTimeout)\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap { response =>\n        Unmarshal(response.entity).to[A]\n      }\n  }\n\n  implicit def postRequestImpl[A](implicit bodyConsumerTimeout: FiniteDuration,\n                                           decoder: FromEntityUnmarshaller[A],\n                                           ec: ExecutionContext,\n                                           mat: Materializer): PostRequest[HttpExt, Future, A] = postRequest(bodyConsumerTimeout)\n\n  def rawPostBodyRequest[Bd](bodyConsumerTimeout: FiniteDuration)(implicit encoder: ToEntityMarshaller[Bd],\n                                                                           ec: ExecutionContext, \n                                                                           mat: Materializer) = new RawPostWithBodyRequest[HttpExt, Future, Bd] {\n    type Resp = HttpResponse\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[HttpExt]): Future[Resp] = {\n      Marshal(body).to[RequestEntity].flatMap { marshalledBody =>\n        val request = mkRequest(deriveUriString(cm, uri), queries, headers - \"Content-Type\").copy(HttpMethods.POST, entity = marshalledBody)\n\n        execRequest(cm.client, request, bodyConsumerTimeout)\n      }\n    }\n  }\n\n  implicit def rawPostBodyRequestImpl[Bd](implicit bodyConsumerTimeout: FiniteDuration,\n                                                   encoder: ToEntityMarshaller[Bd],\n                                                   ec: ExecutionContext,\n                                                   mat: Materializer): RawPostWithBodyRequest[HttpExt, Future, Bd] = rawPostBodyRequest(bodyConsumerTimeout)\n\n  def postBodyRequest[Bd, A](bodyConsumerTimeout: FiniteDuration)(implicit encoder: ToEntityMarshaller[Bd],\n                                                                           decoder: FromEntityUnmarshaller[A],\n                                                                           ec: ExecutionContext, \n                                                                           mat: Materializer) = new PostWithBodyRequest[HttpExt, Future, Bd, A] {\n    private val raw = rawPostBodyRequest(bodyConsumerTimeout)\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[HttpExt]): Future[A] =\n      raw(uri, queries, headers, body, cm).flatMap { response =>\n        Unmarshal(response.entity).to[A]\n      }\n  }\n\n  implicit def postBodyRequestImpl[Bd, A](implicit bodyConsumerTimeout: FiniteDuration,\n                                                   encoder: ToEntityMarshaller[Bd],\n                                                   decoder: FromEntityUnmarshaller[A],\n                                                   ec: ExecutionContext,\n                                                   mat: Materializer): PostWithBodyRequest[HttpExt, Future, Bd, A] = postBodyRequest(bodyConsumerTimeout)\n\n  def rawDeleteRequest(bodyConsumerTimeout: FiniteDuration)(implicit ec: ExecutionContext, \n                                                                     mat: Materializer) = new RawDeleteRequest[HttpExt, Future] {\n    type Resp = HttpResponse\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[Resp] = {\n      val request = mkRequest(deriveUriString(cm, uri), queries, headers).copy(HttpMethods.DELETE)\n\n      execRequest(cm.client, request, bodyConsumerTimeout)\n    }\n  }\n\n  implicit def rawDeleteRequestImpl(implicit bodyConsumerTimeout: FiniteDuration,\n                                             ec: ExecutionContext,\n                                             mat: Materializer): RawDeleteRequest[HttpExt, Future] = rawDeleteRequest(bodyConsumerTimeout)\n\n  def deleteRequest[A](bodyConsumerTimeout: FiniteDuration)(implicit decoder: FromEntityUnmarshaller[A],\n                                                                     ec: ExecutionContext, \n                                                                     mat: Materializer) = new DeleteRequest[HttpExt, Future, A] {\n    private val raw = rawDeleteRequest(bodyConsumerTimeout)\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[HttpExt]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap { response =>\n        Unmarshal(response.entity).to[A]\n      }\n  }\n\n  implicit def deleteRequestImpl[A](implicit bodyConsumerTimeout: FiniteDuration,\n                                             decoder: FromEntityUnmarshaller[A],\n                                             ec: ExecutionContext,\n                                             mat: Materializer): DeleteRequest[HttpExt, Future, A] = deleteRequest(bodyConsumerTimeout)\n}\n"
  },
  {
    "path": "akka-http-server/src/main/scala/typedapi/server/akkahttp/package.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared.MethodType\nimport shapeless._\nimport shapeless.ops.hlist.Prepend\nimport akka.http.scaladsl.{HttpExt, Http}\nimport akka.http.scaladsl.model._\nimport akka.http.scaladsl.unmarshalling.{Unmarshal, FromEntityUnmarshaller}\nimport akka.http.scaladsl.marshalling.{Marshal, ToEntityMarshaller}\nimport akka.stream.Materializer\nimport akka.stream.scaladsl.Sink\n\nimport scala.collection.mutable.Builder\nimport scala.concurrent.{Future, ExecutionContext}\nimport scala.annotation.tailrec\n\npackage object akkahttp {\n\n  case class AkkaHttpHeaderParseException(msg: String) extends Exception(msg)\n\n  private def getHeaders(raw: Map[String, String]): List[HttpHeader] = \n    raw.map { case (key, value) => HttpHeader.parse(key, value) match {\n      case HttpHeader.ParsingResult.Ok(header, _) => header\n      case HttpHeader.ParsingResult.Error(cause)  => throw AkkaHttpHeaderParseException(cause.formatPretty)\n    }}(collection.breakOut)\n\n  implicit def noReqBodyExecutor[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, FOut](implicit encoder: ToEntityMarshaller[FOut], ec: ExecutionContext) = \n    new NoReqBodyExecutor[El, KIn, VIn, M, Future, FOut] {\n      type R   = HttpRequest\n      type Out = Future[HttpResponse]\n\n      def apply(req: R, eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, VIn, Future, FOut]): Either[ExtractionError, Out] = {\n        extract(eReq, endpoint).right.map { extracted =>\n          execute(extracted, endpoint).flatMap {\n            case Right((code, response)) =>\n              Marshal(response).to[ResponseEntity].map { marshalledBody =>\n                HttpResponse(status = StatusCode.int2StatusCode(code.statusCode), entity = marshalledBody, headers = getHeaders(endpoint.headers))\n              }\n\n            case Left(HttpError(code, msg)) =>\n              Future.successful(HttpResponse(status = StatusCode.int2StatusCode(code.statusCode), entity = msg, headers = getHeaders(endpoint.headers)))\n          }\n        }\n      }\n    }\n\n  implicit def withReqBodyExecutor[El <: HList, KIn <: HList, VIn <: HList, Bd, M <: MethodType, ROut <: HList, POut <: HList, FOut]\n    (implicit encoder: ToEntityMarshaller[FOut], \n              decoder: FromEntityUnmarshaller[Bd],\n              _prepend: Prepend.Aux[ROut, Bd :: HNil, POut], \n              _eqProof: POut =:= VIn,\n              mat: Materializer,\n              ec: ExecutionContext) = new ReqBodyExecutor[El, KIn, VIn, Bd, M, ROut, POut, Future, FOut] {\n    type R   = HttpRequest\n    type Out = Future[HttpResponse]\n\n    implicit val prepend = _prepend\n    implicit val eqProof = _eqProof\n\n    def apply(req: R, eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, (BodyType[Bd], ROut), Future, FOut]): Either[ExtractionError, Out] = {\n      extract(eReq, endpoint).right.map { case (_, extracted) =>\n        for {\n          body     <- Unmarshal(req.entity).to[Bd]\n          response <- execute(extracted, body, endpoint).flatMap {\n            case Right((code, response)) =>\n              Marshal(response).to[ResponseEntity].map { marshalledBody =>\n                HttpResponse(status = StatusCode.int2StatusCode(code.statusCode), entity = marshalledBody, headers = getHeaders(endpoint.headers))\n              }\n\n            case Left(HttpError(code, msg)) =>\n              Future.successful(HttpResponse(status = StatusCode.int2StatusCode(code.statusCode), entity = msg, headers = getHeaders(endpoint.headers)))\n          }\n        } yield response\n      }\n    }\n  }\n\n  implicit def mountEndpoints(implicit mat: Materializer) = new MountEndpoints[HttpExt, HttpRequest, Future[HttpResponse]] {\n    type Out = Future[Http.ServerBinding]\n\n    def apply(server: ServerManager[HttpExt], endpoints: List[Serve[HttpRequest, Future[HttpResponse]]]): Out = {\n      val service: HttpRequest => Future[HttpResponse] = request => {\n        def execute(eps: List[Serve[HttpRequest, Future[HttpResponse]]], eReq: EndpointRequest): Future[HttpResponse] = eps match {\n          case collection.immutable.::(endpoint, tail) => endpoint(request, eReq) match {\n            case Right(response)            => response\n            case Left(RouteNotFound)        => execute(tail, eReq)\n            case Left(BadRouteRequest(msg)) => Future.successful(HttpResponse(400, entity = msg))\n          }\n\n          case Nil => Future.successful(HttpResponse(404, entity = \"uri = \" + request.uri))\n        }\n\n        @tailrec\n        def toListPath(path: Uri.Path, agg: Builder[String, List[String]]): List[String] = path match {\n          case Uri.Path.Slash(tail)      => toListPath(tail, agg)\n          case Uri.Path.Segment(p, tail) => toListPath(tail, agg += p)\n          case Uri.Path.Empty            => agg.result()\n        }\n\n        val eReq = EndpointRequest(\n          request.method.name,\n          toListPath(request.uri.path, List.newBuilder),\n          request.uri.query().toMultiMap,\n          request.headers.map(header => header.lowercaseName -> header.value)(collection.breakOut)\n        )\n\n        if (request.method.name == \"OPTIONS\") {\n          Future.successful(HttpResponse(headers = getHeaders(optionsHeaders(endpoints, eReq))))\n        }\n        else\n          execute(endpoints, eReq)\n      }\n    \n      server.server.bind(server.host, server.port).to(Sink.foreach { connection =>\n        connection.handleWithAsyncHandler(service)\n      }).run()\n    }\n  }\n}\n"
  },
  {
    "path": "ammonite-client-support/src/main/scala/typedapi/client/package.scala",
    "content": "package typedapi.client\n\nimport typedapi.util._\nimport scalaj.http._\n\npackage object amm {\n\n  type Id[A]       = scalajhttp.Id[A]\n  type Blocking[A] = scalajhttp.Blocking[A]\n\n  def clientManager(host: String, port: Int): ClientManager[Http.type] = ClientManager(Http, host, port)\n  def clientManager(host: String): ClientManager[Http.type] = ClientManager(Http, host)\n\n  implicit def rawGetRequestAmm = scalajhttp.rawGetRequest\n  implicit def getRequestAmm[A](implicit decoder: Decoder[Id, A]) = scalajhttp.getRequest[A]\n\n  implicit def rawPutRequestAmm = scalajhttp.rawPutRequest\n  implicit def putRequestAmm[A](implicit decoder: Decoder[Id, A]) = scalajhttp.putRequest[A]\n\n  implicit def rawPutBodyRequestAmm[Bd](implicit encoder: Encoder[Id, Bd]) = scalajhttp.rawPutBodyRequest[Bd]\n  implicit def putBodyRequestAmm[Bd, A](implicit encoder: Encoder[Id, Bd], decoder: Decoder[Id, A]) = scalajhttp.putBodyRequest[Bd, A]\n\n  implicit def rawPostRequestAmm = scalajhttp.rawPostRequest\n  implicit def postRequest[A](implicit decoder: Decoder[Id, A]) = scalajhttp.postRequest[A]\n\n  implicit def rawPostBodyRequestAm[Bd](implicit encoder: Encoder[Id, Bd]) = scalajhttp.rawPostBodyRequest[Bd]\n  implicit def postBodyRequestAmm[Bd, A](implicit encoder: Encoder[Id, Bd], decoder: Decoder[Id, A]) = scalajhttp.postBodyRequest[Bd, A]\n\n  implicit def rawDeleteRequestAmm = scalajhttp.rawDeleteRequest\n  implicit def deleteRequestAmm[A](implicit decoder: Decoder[Id, A]) = scalajhttp.deleteRequest[A]\n}\n"
  },
  {
    "path": "build.sbt",
    "content": "import sbt.Keys._\n\nval `compiler-2.12` = Seq(\n  \"-deprecation\",\n  \"-encoding\", \"utf-8\",\n  \"-explaintypes\",\n  \"-feature\",\n  \"-unchecked\",\n  \"-Xfatal-warnings\",\n  \"-Xfuture\",\n  \"-Xlint:inaccessible\",\n  \"-Xlint:infer-any\",\n  \"-Xlint:missing-interpolator\",\n  \"-Xlint:option-implicit\",\n  \"-Xlint:type-parameter-shadow\",\n  \"-Xlint:unsound-match\",\n  \"-Ywarn-dead-code\",\n  \"-Ywarn-inaccessible\",\n  \"-Ywarn-infer-any\",\n  \"-Ywarn-numeric-widen\",\n  //   \"-Ywarn-unused:implicits\", -> get errors for implicit evidence\n  \"-Ywarn-unused:imports\",\n  //   \"-Ywarn-unused:locals\",\n  \"-Ywarn-unused:privates\"\n)\n\nval `compiler-2.11` = Seq(\n  \"-deprecation\",\n  \"-encoding\", \"utf-8\",\n  \"-explaintypes\",\n  \"-feature\",\n  \"-unchecked\",\n  \"-Xfatal-warnings\",\n  \"-Xfuture\",\n  \"-Xlint:inaccessible\",\n  \"-Xlint:infer-any\",\n  \"-Xlint:missing-interpolator\",\n  \"-Xlint:option-implicit\",\n  \"-Xlint:type-parameter-shadow\",\n  \"-Xlint:unsound-match\",\n  \"-Ywarn-dead-code\",\n  \"-Ywarn-numeric-widen\",\n  \"-Ywarn-unused\",\n  \"-Ywarn-inaccessible\",\n  \"-Ywarn-infer-any\"\n)\n\nlazy val commonSettings = Seq(\n  organization  := \"com.github.pheymann\",\n  version       := \"0.2.0\",\n  crossScalaVersions := Seq(\"2.11.11\", \"2.12.4\"),\n  scalaVersion       := \"2.12.4\",\n  scalacOptions      ++= { CrossVersion.partialVersion(scalaVersion.value) match {\n    case Some((2, 12)) => `compiler-2.12`\n    case Some((2, 11)) => `compiler-2.11`\n    case _             => Seq.empty[String]\n  }},\n  publishTo := sonatypePublishTo.value\n)\n\nlazy val mavenSettings = Seq(\n  sonatypeProfileName := \"pheymann\",\n  publishMavenStyle   := true,\n  pomExtra in Global  := {\n    <url>https://github.com/pheymann/typedapi</url>\n      <licenses>\n        <license>\n          <name>MIT</name>\n          <url>https://github.com/pheymann/typedapi/blob/master/LICENSE</url>\n        </license>\n      </licenses>\n      <scm>\n        <connection>scm:git:github.com/pheymann/typedapi</connection>\n        <developerConnection>scm:git:git@github.com:pheymann/typedapi</developerConnection>\n        <url>github.com/pheymann/typedapi</url>\n      </scm>\n      <developers>\n        <developer>\n          <id>pheymann</id>\n          <name>Paul Heymann</name>\n          <url>https://github.com/pheymann</url>\n        </developer>\n      </developers>\n  }\n)\n\nlazy val typedapi = project\n  .in(file(\".\"))\n  .settings(commonSettings: _*)\n  .aggregate(\n    `shared-js`, \n    `shared-jvm`, \n    `client-js`, \n    `client-jvm`, \n    server, \n    `http4s-client`, \n    `http4s-server`, \n    `akka-http-client`,\n    `akka-http-server`,\n    `js-client`,\n    `scalaj-http-client`,\n    `http-support-tests`,\n    `ammonite-client-support`\n  )\n\nlazy val shared = crossProject.crossType(CrossType.Pure)\n  .in(file(\"shared\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-shared\",\n    libraryDependencies ++= Dependencies.shared\n  )\n\nlazy val `shared-js` = shared.js\nlazy val `shared-jvm` = shared.jvm\n\nlazy val client = crossProject.crossType(CrossType.Pure)\n  .in(file(\"client\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-client\",\n    libraryDependencies ++= Dependencies.client\n  )\n  .dependsOn(shared)\n\nlazy val `client-js` = client.js\nlazy val `client-jvm` = client.jvm\n\nlazy val server = project\n  .in(file(\"server\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-server\",\n    libraryDependencies ++= Dependencies.server\n  )\n  .dependsOn(`shared-jvm`)\n\n\nlazy val `http4s-client` = project\n  .in(file(\"http4s-client\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-http4s-client\",\n    libraryDependencies ++= Dependencies.http4sClient,\n  )\n  .dependsOn(`client-jvm`)\n\nlazy val `http4s-server` = project\n  .in(file(\"http4s-server\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-http4s-server\",\n    libraryDependencies ++= Dependencies.http4sServer,\n  )\n  .dependsOn(server)\n\nlazy val `akka-http-client` = project\n  .in(file(\"akka-http-client\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-akka-http-client\",\n    libraryDependencies ++= Dependencies.akkaHttpClient\n  )\n  .dependsOn(`client-jvm`)\n\nlazy val `akka-http-server` = project\n  .in(file(\"akka-http-server\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-akka-http-server\",\n    libraryDependencies ++= Dependencies.akkaHttpServer\n  )\n  .dependsOn(server)\n\nlazy val `js-client` = project\n  .in(file(\"js-client\"))\n  .enablePlugins(ScalaJSPlugin)\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-js-client\",\n    libraryDependencies ++= Seq(\n      \"org.scala-js\" %%% \"scalajs-dom\" % \"0.9.6\" % Compile\n    )\n  )\n  .dependsOn(`client-js`)\n\nlazy val `scalaj-http-client` = project\n  .in(file(\"scalaj-http-client\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-scalaj-http-client\",\n    libraryDependencies ++= Dependencies.scalajHttpClient\n  )\n  .dependsOn(`client-jvm`)\n\nlazy val `http-support-tests` = project\n  .in(file(\"http-support-tests\"))\n  .settings(\n    commonSettings,\n    parallelExecution in Test := false,\n    libraryDependencies ++= Dependencies.httpSupportTests\n  )\n  .dependsOn(`http4s-client`, `http4s-server`, `akka-http-client`, `akka-http-server`, `scalaj-http-client`)\n\nlazy val `ammonite-client-support` = project\n  .in(file(\"ammonite-client-support\"))\n  .settings(\n    commonSettings,\n    mavenSettings,\n    name := \"typedapi-ammonite-client\",\n    libraryDependencies ++= Dependencies.ammoniteSupport\n  )\n  .dependsOn(`scalaj-http-client`)\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/ApiRequest.scala",
    "content": "package typedapi.client\n\nimport RequestDataBuilder.{Data, DataWithBody}\nimport typedapi.shared._\nimport shapeless._\n\nimport scala.language.higherKinds\nimport scala.annotation.implicitNotFound\n\n/** Basic api request element. Provides a function to create an effect representing the actual request. */\n@implicitNotFound(\"\"\"Cannot find RawApiRequest instance for ${M}.\n\ncontext: ${F}\"\"\")\ntrait RawApiRequest[M <: MethodType, D <: HList, C, F[_]] {\n\n  type Resp\n\n  def apply(data: D, cm: ClientManager[C]): F[Resp]\n}\n\n@implicitNotFound(\"\"\"Cannot find ApiRequest instance for ${M}. Do you miss some implicit value e.g. encoders/decoders?\n\nouput: ${Out}\ncontext: ${F}\"\"\")\ntrait ApiRequest[M <: MethodType, D <: HList, C, F[_], Out] {\n\n  def apply(data: D, cm: ClientManager[C]): F[Out]\n}\n\ntrait RawApiWithoutBodyRequest[M <: MethodType, C, F[_]] extends RawApiRequest[M, Data, C, F] {\n\n  def apply(data: Data, cm: ClientManager[C]): F[Resp] = {\n    val (uri :: queries :: headers :: HNil): Data = data\n\n    apply(uri, queries, headers, cm)\n  }\n\n  def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[C]): F[Resp]\n}\n\ntrait ApiWithoutBodyRequest[M <: MethodType, C, F[_], Out] extends ApiRequest[M, Data, C, F, Out] {\n\n  def apply(data: Data, cm: ClientManager[C]): F[Out] = {\n    val (uri :: queries :: headers :: HNil): Data = data\n\n    apply(uri, queries, headers, cm)\n  }\n\n  def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[C]): F[Out]\n}\n\ntrait RawApiWithBodyRequest[M <: MethodType, C, F[_], Bd] extends RawApiRequest[M, DataWithBody[Bd], C, F] {\n\n  def apply(data: DataWithBody[Bd], cm: ClientManager[C]): F[Resp] = {\n    val (uri :: queries :: headers :: body :: HNil): DataWithBody[Bd] = data\n\n    apply(uri, queries, headers, body, cm)\n  }\n\n  def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[C]): F[Resp]\n}\n\ntrait ApiWithBodyRequest[M <: MethodType, C, F[_], Bd, Out] extends ApiRequest[M, DataWithBody[Bd], C, F, Out] {\n\n  def apply(data: DataWithBody[Bd], cm: ClientManager[C]): F[Out] = {\n    val (uri :: queries :: headers :: body :: HNil): DataWithBody[Bd] = data\n\n    apply(uri, queries, headers, body, cm)\n  }\n\n  def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[C]): F[Out]\n}\n\ntrait RawGetRequest[C, F[_]] extends RawApiWithoutBodyRequest[GetCall, C, F]\ntrait GetRequest[C, F[_], A] extends ApiWithoutBodyRequest[GetCall, C, F, A]\ntrait RawPutRequest[C, F[_]] extends RawApiWithoutBodyRequest[PutCall, C, F]\ntrait PutRequest[C, F[_], A] extends ApiWithoutBodyRequest[PutCall, C, F, A]\ntrait RawPutWithBodyRequest[C, F[_], Bd] extends RawApiWithBodyRequest[PutWithBodyCall, C, F, Bd]\ntrait PutWithBodyRequest[C, F[_], Bd, A] extends ApiWithBodyRequest[PutWithBodyCall, C, F, Bd, A]\ntrait RawPostRequest[C, F[_]] extends RawApiWithoutBodyRequest[PostCall, C, F]\ntrait PostRequest[C, F[_], A] extends ApiWithoutBodyRequest[PostCall, C, F, A]\ntrait RawPostWithBodyRequest[C, F[_], Bd] extends RawApiWithBodyRequest[PostWithBodyCall, C, F, Bd]\ntrait PostWithBodyRequest[C, F[_], Bd, A] extends ApiWithBodyRequest[PostWithBodyCall, C, F, Bd, A]\ntrait RawDeleteRequest[C, F[_]] extends RawApiWithoutBodyRequest[DeleteCall, C, F]\ntrait DeleteRequest[C, F[_], A] extends ApiWithoutBodyRequest[DeleteCall, C, F, A]\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/ClientManager.scala",
    "content": "package typedapi.client\n\n/** Provides a supported client instance and some basic configuration. */\nfinal case class ClientManager[C](client: C, host: String, portO: Option[Int]) {\n\n  val base = portO match {\n    case Some(p) => s\"$host:$p\"\n    case None    => host\n  }\n}\n\nobject ClientManager {\n\n  def apply[C](client: C, host: String, port: Int): ClientManager[C] = ClientManager(client, host, Some(port))\n  def apply[C](client: C, host: String): ClientManager[C] = ClientManager(client, host, None)\n}\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/ExecutableDerivation.scala",
    "content": "package typedapi.client\n\nimport typedapi.shared.{MethodType, MediaType}\nimport shapeless._\nimport shapeless.labelled.FieldType\n\nimport scala.language.higherKinds\n\n/** Helper class to match the [[RequestDataBuilder]] with an [[ApiRequest]] instance. */\nfinal class ExecutableDerivation[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, MT <: MediaType, O, D <: HList]\n  (builder: RequestDataBuilder.Aux[El, KIn, VIn, M, FieldType[MT, O], D], input: VIn) {\n\n  final class Derivation[F[_]] {\n\n    def apply[C](cm: ClientManager[C])(implicit req: ApiRequest[M, D, C, F, O]): F[O] = {\n      val data = builder(input, List.newBuilder, Map.empty, Map.empty)\n\n      req(data, cm)\n    }\n\n    def raw[C](cm: ClientManager[C])(implicit req: RawApiRequest[M, D, C, F]): F[req.Resp] = {\n      val data = builder(input, List.newBuilder, Map.empty, Map.empty)\n\n      req(data, cm)\n    }\n  }\n\n  def run[F[_]]: Derivation[F] = new Derivation[F]\n}\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/ExecutablesFromHList.scala",
    "content": "package typedapi.client\n\nimport typedapi.shared.{MethodType, MediaType}\nimport shapeless._\nimport shapeless.labelled.FieldType\nimport shapeless.ops.function.FnFromProduct\n\n/** Derives executables from list of RequestBuilders. */\nsealed trait ExecutablesFromHList[H <: HList] {\n\n  type Out <: HList\n\n  def apply(h: H): Out\n}\n\nobject ExecutablesFromHList extends ExecutablesFromHListLowPrio {\n\n  type Aux[H <: HList, Out0 <: HList] = ExecutablesFromHList[H] { type Out = Out0 }\n}\n\ntrait ExecutablesFromHListLowPrio {\n\n  implicit val noExecutable = new ExecutablesFromHList[HNil] {\n    type Out = HNil\n\n    def apply(h: HNil): Out = HNil\n  }\n\n  implicit def deriveExcutable[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, MT <: MediaType, O, D <: HList, T <: HList]\n    (implicit next: ExecutablesFromHList[T],\n              vinToFn: FnFromProduct[VIn => ExecutableDerivation[El, KIn, VIn, M, MT, O, D]]) =\n    new ExecutablesFromHList[RequestDataBuilder.Aux[El, KIn, VIn, M, FieldType[MT, O], D] :: T] {\n      type Out = vinToFn.Out :: next.Out\n\n      def apply(comps: RequestDataBuilder.Aux[El, KIn, VIn, M, FieldType[MT, O], D] :: T): Out = {\n        val fn = vinToFn.apply(input => new ExecutableDerivation[El, KIn, VIn, M, MT, O, D](comps.head, input))\n\n        fn :: next(comps.tail)\n      }\n    }\n}\n\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/FilterServerElements.scala",
    "content": "package typedapi.client\n\nimport typedapi.shared._\nimport shapeless._\n\n//TODO replace with Typelevelfoldleft\nsealed trait FilterServerElements[H <: HList] {\n\n  type Out <: HList\n}\n\nsealed trait FilterServerElementsLowPrio {\n\n  implicit val filterServerResult = new FilterServerElements[HNil] {\n    type Out = HNil\n  }\n\n  implicit def filterServerKeep[El, T <: HList](implicit next: FilterServerElements[T]) = new FilterServerElements[El :: T] {\n    type Out = El :: next.Out\n  }\n}\n\nobject FilterServerElements extends FilterServerElementsLowPrio {\n\n  type Aux[H <: HList, Out0 <: HList] = FilterServerElements[H] { type Out = Out0 }\n\n  implicit def filterServerHeaderMatch[K, V, T <: HList](implicit next: FilterServerElements[T]) = new FilterServerElements[ServerHeaderMatchParam[K, V] :: T] {\n    type Out = next.Out\n  }\n\n  implicit def filterServerHeaderSend[K, V, T <: HList](implicit next: FilterServerElements[T]) = new FilterServerElements[ServerHeaderSendElement[K, V] :: T] {\n    type Out = next.Out\n  }\n}\n\nsealed trait FilterServerElementsList[H <: HList] {\n\n  type Out <: HList\n}\n\nobject FilterServerElementsList {\n\n  type Aux[H <: HList, Out0 <: HList] = FilterServerElementsList[H] { type Out = Out0 }\n\n  implicit val filterServerListResult = new FilterServerElementsList[HNil] {\n    type Out = HNil\n  }\n\n  implicit def filterServerListStep[Api <: HList, T <: HList](implicit filtered: FilterServerElements[Api], next: FilterServerElementsList[T]) = \n    new FilterServerElementsList[Api :: T] {\n      type Out = filtered.Out :: next.Out\n    }\n}\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/RequestDataBuilder.scala",
    "content": "package typedapi.client\n\nimport typedapi.shared._\nimport shapeless._\nimport shapeless.labelled.FieldType\n\nimport scala.collection.mutable.Builder\nimport scala.annotation.implicitNotFound\n\n/** Compiles type level api description into a function returning request data (uri, query, header, body) and return-type `A` which are used for a request. */\n@implicitNotFound(\"\"\"Woops, you shouldn't be here. We cannot find the RequestDataBuilder. This seems to be a bug.\n\nelements: ${El}\ninput keys: ${KIn}\ninput values: ${VIn}\nmethod: ${M}\nexpected result: ${O}\"\"\")\ntrait RequestDataBuilder[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O] {\n\n  type Out <: HList\n\n  def apply(inputs: VIn, \n            uri: Builder[String, List[String]], \n            queries: Map[String, List[String]], \n            headers: Map[String, String]): Out\n}\n\nobject RequestDataBuilder extends RequestDataBuilderMediumPrio {\n\n  type Aux[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O, Out0 <: HList] = RequestDataBuilder[El, KIn, VIn, M, O] { type Out = Out0 }\n}\n\ntrait RequestDataBuilderLowPrio {\n\n  implicit def pathCompiler[S, T <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O](implicit wit: Witness.Aux[S], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) = \n    new RequestDataBuilder[S :: T, KIn, VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        compiler(inputs, uri += wit.value.toString(), queries, headers)\n      }\n    }\n  \n  implicit def segmentInputCompiler[T <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, O](implicit compiler: RequestDataBuilder[T, KIn, VIn, M, O]) = \n    new RequestDataBuilder[SegmentInput :: T, K :: KIn, V :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: V :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val segValue = inputs.head\n\n        compiler(inputs.tail, uri += segValue.toString(), queries, headers)\n      }\n    }\n\n  implicit def queryInputCompiler[T <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[QueryInput :: T, K :: KIn, V :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: V :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val queryName  = show.show(wit.value)\n        val queryValue = inputs.head\n\n        compiler(inputs.tail, uri, Map((queryName, List(queryValue.toString()))) ++ queries, headers)\n      }\n    }\n\n  implicit def headerInputCompiler[T <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[HeaderInput :: T, K :: KIn, V :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: V :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val headerName  = show.show(wit.value)\n        val headerValue = inputs.head\n\n        compiler(inputs.tail, uri, queries, Map((headerName, headerValue.toString())) ++ headers)\n      }\n    }\n\n  implicit def fixedHeaderCompiler[K, V, T <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit kWit: Witness.Aux[K], vWit: Witness.Aux[V], kShow: WitnessToString[K], vShow: WitnessToString[V], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[FixedHeader[K, V] :: T, KIn, VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val key   = kShow.show(kWit.value)\n        val value = vShow.show(vWit.value)\n\n        compiler(inputs, uri, queries, Map((key, value)) ++ headers)\n      }\n    }\n\n  implicit def clientHeaderCompiler[K, V, T <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit kWit: Witness.Aux[K], vWit: Witness.Aux[V], kShow: WitnessToString[K], vShow: WitnessToString[V], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[ClientHeader[K, V] :: T, KIn, VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val key   = kShow.show(kWit.value)\n        val value = vShow.show(vWit.value)\n\n        compiler(inputs, uri, queries, Map((key, value)) ++ headers)\n      }\n    }\n\n  implicit def clientHeaderInputCompiler[K, V, T <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit kWit: Witness.Aux[K], kShow: WitnessToString[K], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[ClientHeaderInput :: T, K :: KIn, V :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: V :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val key   = kShow.show(kWit.value)\n        val value = inputs.head.toString\n\n        compiler(inputs.tail, uri, queries, Map((key, value)) ++ headers)\n      }\n    }\n\n  implicit def clientHeaderCollInputCompiler[V, T <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[ClientHeaderCollInput :: T, KIn, Map[String, V] :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: Map[String, V] :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val coll = inputs.head.mapValues(_.toString)\n\n        compiler(inputs.tail, uri, queries, coll ++ headers)\n      }\n    }\n\n  type Data             = List[String] :: Map[String, List[String]] :: Map[String, String] :: HNil\n  type DataWithBody[Bd] = List[String] :: Map[String, List[String]] :: Map[String, String] :: Bd :: HNil\n\n  private def accept[MT <: MediaType](headers: Map[String, String], media: MT): Map[String, String] =\n    Map((\"Accept\", media.value)) ++ headers\n\n  implicit def getCompiler[MT <: MediaType, A](implicit media: Witness.Aux[MT]) = new RequestDataBuilder[HNil, HNil, HNil, GetCall, FieldType[MT, A]] {\n    type Out = Data\n\n    def apply(inputs: HNil, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n      val out = uri.result() :: queries :: accept(headers, media.value) :: HNil\n\n      out\n    }\n  }\n\n  implicit def putCompiler[MT <: MediaType, A](implicit media: Witness.Aux[MT]) = new RequestDataBuilder[HNil, HNil, HNil, PutCall, FieldType[MT, A]] {\n    type Out = Data\n\n    def apply(inputs: HNil, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n      val out = uri.result() :: queries :: accept(headers, media.value) :: HNil\n\n      out\n    }\n  }\n\n  implicit def putWithBodyCompiler[BMT <: MediaType, Bd, MT <: MediaType, A](implicit media: Witness.Aux[MT]) = \n    new RequestDataBuilder[HNil, FieldType[BMT, BodyField.T] :: HNil, Bd :: HNil, PutWithBodyCall, FieldType[MT, A]] {\n      type Out = DataWithBody[Bd]\n\n      def apply(inputs: Bd :: HNil, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val out = uri.result() :: queries :: accept(headers, media.value) :: inputs.head :: HNil\n\n        out\n      }\n    }\n\n  implicit def postCompiler[MT <: MediaType, A](implicit media: Witness.Aux[MT]) = new RequestDataBuilder[HNil, HNil, HNil, PostCall, FieldType[MT, A]] {\n    type Out = Data\n\n    def apply(inputs: HNil, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n      val out = uri.result() :: queries :: accept(headers, media.value) :: HNil\n\n      out\n    }\n  }\n\n  implicit def postWithBodyCompiler[BMT <: MediaType, Bd, MT <: MediaType, A](implicit media: Witness.Aux[MT]) = \n    new RequestDataBuilder[HNil, FieldType[BMT, BodyField.T] :: HNil, Bd :: HNil, PostWithBodyCall, FieldType[MT, A]] {\n      type Out = DataWithBody[Bd]\n\n      def apply(inputs: Bd :: HNil, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val out = uri.result() :: queries :: accept(headers, media.value) :: inputs.head :: HNil\n\n        out\n      }\n    }\n\n  implicit def deleteCompiler[MT <: MediaType, A](implicit media: Witness.Aux[MT]) = new RequestDataBuilder[HNil, HNil, HNil, DeleteCall, FieldType[MT, A]] {\n    type Out = Data\n\n    def apply(inputs: HNil, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n      val out = uri.result() :: queries :: accept(headers, media.value) :: HNil\n\n      out\n    }\n  }\n}\n\ntrait RequestDataBuilderMediumPrio extends RequestDataBuilderLowPrio {\n\n  implicit def queryOptInputCompiler[T <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[QueryInput :: T, K :: KIn, Option[V] :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: Option[V] :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val queryName      = show.show(wit.value)\n        val queryValue     = inputs.head\n        val updatedQueries = queryValue.fold(queries)(q => Map(queryName -> List(q.toString())) ++ queries)\n\n        compiler(inputs.tail, uri, updatedQueries, headers)\n      }\n    }\n\n  implicit def queryListInputCompiler[T <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[QueryInput :: T, K :: KIn, List[V] :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: List[V] :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val queryName  = show.show(wit.value)\n        val queryValue = inputs.head\n\n        if (queryValue.isEmpty)\n          compiler(inputs.tail, uri, queries, headers)\n        else\n          compiler(inputs.tail, uri, Map((queryName, queryValue.map(_.toString()))) ++ queries, headers)\n      }\n    }\n\n  implicit def headersOptInputCompiler[T <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, O]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], compiler: RequestDataBuilder[T, KIn, VIn, M, O]) =\n    new RequestDataBuilder[HeaderInput :: T, K :: KIn, Option[V] :: VIn, M, O] {\n      type Out = compiler.Out\n\n      def apply(inputs: Option[V] :: VIn, uri: Builder[String, List[String]], queries: Map[String, List[String]], headers: Map[String, String]): Out = {\n        val headerName     = show.show(wit.value)\n        val headerValue    = inputs.head\n        val updatedHeaders = headerValue.fold(headers)(h => Map(headerName -> h.toString()) ++ headers)\n\n        compiler(inputs.tail, uri, queries, updatedHeaders)\n      }\n    }\n}\n\n@implicitNotFound(\"\"\"Woops, you shouldn't be here. We cannot find the RequestDataBuilderList. This seems to be a bug.\n\nlist: ${H}\"\"\")\ntrait RequestDataBuilderList[H <: HList] {\n\n  type Out <: HList\n\n  def builders: Out\n}\n\nobject RequestDataBuilderList extends RequestDataBuilderListLowPrio {\n\n  type Aux[H <: HList, Out0 <: HList] = RequestDataBuilderList[H] { type Out = Out0 }\n}\n\ntrait RequestDataBuilderListLowPrio {\n\n  implicit def lastCompilerList[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O, D <: HList](implicit builder: RequestDataBuilder.Aux[El, KIn, VIn, M, O, D]) = \n    new RequestDataBuilderList[(El, KIn, VIn, M, O) :: HNil] {\n      type Out = RequestDataBuilder.Aux[El, KIn, VIn, M, O, D] :: HNil\n\n      val builders = builder :: HNil\n    }\n\n  implicit def builderList[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, O, D <: HList, T <: HList](implicit builder: RequestDataBuilder.Aux[El, KIn, VIn, M, O, D], next: RequestDataBuilderList[T]) = \n    new RequestDataBuilderList[(El, KIn, VIn, M, O) :: T] {\n      type Out = RequestDataBuilder.Aux[El, KIn, VIn, M, O, D] :: next.Out\n\n      val builders = builder :: next.builders\n    }\n}\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/package.scala",
    "content": "package typedapi\n\nimport typedapi.shared._\nimport shapeless._\nimport shapeless.labelled.FieldType\nimport shapeless.ops.hlist.Tupler\nimport shapeless.ops.function.FnFromProduct\n\npackage object client extends TypeLevelFoldLeftLowPrio \n                      with TypeLevelFoldLeftListLowPrio\n                      with WitnessToStringLowPrio\n                      with ApiTransformer {\n\n  def deriveUriString(cm: ClientManager[_], uri: List[String]): String = cm.base + \"/\" + uri.mkString(\"/\")\n\n  def derive[H <: HList, FH <: HList, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, MT <: MediaType, Out, D <: HList]\n    (apiList: ApiTypeCarrier[H])\n    (implicit filter: FilterServerElements.Aux[H, FH],\n              folder: Lazy[TypeLevelFoldLeft.Aux[FH, Unit, (El, KIn, VIn, M, FieldType[MT, Out])]],\n              builder: RequestDataBuilder.Aux[El, KIn, VIn, M, FieldType[MT, Out], D],\n              inToFn: FnFromProduct[VIn => ExecutableDerivation[El, KIn, VIn, M, MT, Out, D]]): inToFn.Out =\n    inToFn.apply(input => new ExecutableDerivation[El, KIn, VIn, M, MT, Out, D](builder, input))\n\n  def deriveAll[H <: HList, FH <: HList, In <: HList, Fold <: HList, B <: HList, Ex <: HList]\n    (apiLists: CompositionCons[H])\n    (implicit filter: FilterServerElementsList.Aux[H, FH],\n              folders: TypeLevelFoldLeftList.Aux[FH, Fold],\n              builderList: RequestDataBuilderList.Aux[Fold, B],\n              executables: ExecutablesFromHList.Aux[B, Ex],\n              tupler: Tupler[Ex]): tupler.Out =\n    executables(builderList.builders).tupled\n}\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/test/RequestInput.scala",
    "content": "package typedapi.client.test\n\nfinal case class ReqInput(method: String,\n                          uri: List[String],\n                          queries: Map[String, List[String]],\n                          headers: Map[String, String])\n\nfinal case class ReqInputWithBody[Bd](method: String, \n                                      uri: List[String], \n                                      queries: Map[String, List[String]], \n                                      headers: Map[String, String],\n                                      body: Bd)\n"
  },
  {
    "path": "client/src/main/scala/typedapi/client/test/package.scala",
    "content": "package typedapi.client\n\nimport scala.language.higherKinds\n\npackage object test {\n\n  type TestClientM = ClientManager[Unit]\n\n  val clientManager: TestClientM = ClientManager((), \"\", 0)\n\n  def testRawGet[F[_]](pure: ReqInput => F[ReqInput]) = new RawGetRequest[Unit, F] {\n    type Resp = ReqInput\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[Resp] = \n      pure(ReqInput(\"GET\", uri, queries, headers))\n  }\n  def testGet[F[_], A](f: ReqInput => F[A]) = new GetRequest[Unit, F, A] {\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[A] = \n      f(ReqInput(\"GET\", uri, queries, headers))\n  }\n\n  def testRawPut[F[_]](pure: ReqInput => F[ReqInput]) = new RawPutRequest[Unit, F] {\n    type Resp = ReqInput\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[Resp] = \n      pure(ReqInput(\"PUT\", uri, queries, headers))\n  }\n  def testPut[F[_], A](f: ReqInput => F[A]) = new PutRequest[Unit, F, A] {\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[A] = \n      f(ReqInput(\"PUT\", uri, queries, headers))\n  }\n\n  def testRawPutWithBody[F[_], Bd](pure: ReqInputWithBody[Bd] => F[ReqInputWithBody[Bd]]) = \n    new RawPutWithBodyRequest[Unit, F, Bd] {\n      type Resp = ReqInputWithBody[Bd]\n\n      def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: TestClientM): F[Resp] = \n        pure(ReqInputWithBody(\"PUT\", uri, queries, headers, body))\n    }\n  def testPutWithBody[F[_], Bd, A](f: ReqInputWithBody[Bd] => F[A]) = \n    new PutWithBodyRequest[Unit, F, Bd, A] {\n      def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: TestClientM): F[A] = \n        f(ReqInputWithBody(\"PUT\", uri, queries, headers, body))\n    }\n\n  def testRawPost[F[_]](pure: ReqInput => F[ReqInput]) = new RawPostRequest[Unit, F] {\n    type Resp = ReqInput\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[Resp] = \n      pure(ReqInput(\"POST\", uri, queries, headers))\n  }\n  def testPost[F[_], A](f: ReqInput => F[A]) = new PostRequest[Unit, F, A] {\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[A] = \n      f(ReqInput(\"POST\", uri, queries, headers))\n  }\n\n  def testRawPostWithBody[F[_], Bd](pure: ReqInputWithBody[Bd] => F[ReqInputWithBody[Bd]]) = \n    new RawPostWithBodyRequest[Unit, F, Bd] {\n    type Resp = ReqInputWithBody[Bd]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: TestClientM): F[Resp] = \n      pure(ReqInputWithBody(\"POST\", uri, queries, headers, body))\n  }\n  def testPostWithBody[F[_], Bd, A](f: ReqInputWithBody[Bd] => F[A]) = \n    new PostWithBodyRequest[Unit, F, Bd, A] {\n      def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: TestClientM): F[A] = \n        f(ReqInputWithBody(\"POST\", uri, queries, headers, body))\n    }\n\n  def testRawDelete[F[_]](pure: ReqInput => F[ReqInput]) = new RawDeleteRequest[Unit, F] {\n    type Resp = ReqInput\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[Resp] = \n      pure(ReqInput(\"DELETE\", uri, queries, headers))\n  }\n  def testDelete[F[_], A](f: ReqInput => F[A]) = new DeleteRequest[Unit, F, A] {\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: TestClientM): F[A] = \n      f(ReqInput(\"DELETE\", uri, queries, headers))\n  }\n}\n"
  },
  {
    "path": "client/src/test/scala/typedapi/client/ClientManagerSpec.scala",
    "content": "package typedapi.client\n\nimport org.specs2.mutable.Specification\n\nfinal class ClientManagerSpec extends Specification {\n\n  \"optional port definition\" >> {\n    ClientManager((), \"my-host\", 80).base === \"my-host:80\"\n    ClientManager((), \"my-host\").base === \"my-host\"\n  }\n}\n"
  },
  {
    "path": "client/src/test/scala/typedapi/client/RequestDataBuilderSpec.scala",
    "content": "package typedapi.client\n\nimport typedapi.dsl._\nimport typedapi.client.test._\n\nimport shapeless.Id\nimport org.specs2.mutable.Specification\n\nfinal class RequestDataBuilderSpec extends Specification {\n\n  case class Foo()\n\n  type Result = (String, List[String], Map[String, String], Map[String, String], Option[Foo])\n\n  implicit val get       = testGet[Id, ReqInput](identity)\n  implicit val put       = testPut[Id, ReqInput](identity)\n  implicit def putB[Bd]  = testPutWithBody[Id, Bd, ReqInputWithBody[Bd]](identity)\n  implicit val post      = testPost[Id, ReqInput](identity)\n  implicit def postB[Bd] = testPostWithBody[Id, Bd, ReqInputWithBody[Bd]](identity)\n  implicit val delete    = testDelete[Id, ReqInput](identity)\n\n  \"executes compiled api\" >> {\n    val cm = clientManager\n\n    \"single api\" >> {\n      \"method\" >> {\n        val api0 = derive(:= :> Get[Json, ReqInput])\n        api0().run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map((\"Accept\", \"application/json\")))\n        val api1 = derive(:= :> Put[Json, ReqInput])\n        api1().run[Id](cm) === ReqInput(\"PUT\", Nil, Map(), Map((\"Accept\", \"application/json\")))\n        val api2 = derive(:= :> Post[Json, ReqInput])\n        api2().run[Id](cm) === ReqInput(\"POST\", Nil, Map(), Map((\"Accept\", \"application/json\")))\n        val api3 = derive(:= :> Delete[Json, ReqInput])\n        api3().run[Id](cm) === ReqInput(\"DELETE\", Nil, Map(), Map((\"Accept\", \"application/json\")))\n      }\n      \n      \"segment\" >> {\n        val api0 = derive(:= :> Segment[Int]('i0) :> Get[Json, ReqInput])\n        api0(0).run[Id](cm) === ReqInput(\"GET\", \"0\" :: Nil, Map(), Map((\"Accept\", \"application/json\")))\n        val api1 = derive(:= :> Segment[Int]('i0) :> Segment[Int]('i1) :> Get[Json, ReqInput])\n        api1(0, 1).run[Id](cm) === ReqInput(\"GET\", \"0\" :: \"1\" :: Nil, Map(), Map((\"Accept\", \"application/json\")))\n      }\n\n      \"query\" >> {\n        val api0 = derive(:= :> Query[Int]('i0) :> Get[Json, ReqInput])\n        api0(0).run[Id](cm) === ReqInput(\"GET\", Nil, Map(\"i0\" -> List(\"0\")), Map((\"Accept\", \"application/json\")))\n        val api1 = derive(:= :> Query[Int]('i0) :> Query[Int]('i1) :> Get[Json, ReqInput])\n        api1(0, 1).run[Id](cm) === ReqInput(\"GET\", Nil, Map(\"i0\" -> List(\"0\"), \"i1\" -> List(\"1\")), Map((\"Accept\", \"application/json\")))\n        val api2 = derive(:= :> Query[List[Int]]('i0) :> Get[Json, ReqInput])\n        api2(List(0, 1)).run[Id](cm) === ReqInput(\"GET\", Nil, Map(\"i0\" -> List(\"0\", \"1\")), Map((\"Accept\", \"application/json\")))\n        api2(Nil).run[Id](cm) === ReqInput(\"GET\", Nil, Map.empty, Map((\"Accept\", \"application/json\")))\n        val api3 = derive(:= :> Query[Option[Int]]('i0) :> Get[Json, ReqInput])\n        api3(Some(0)).run[Id](cm) === ReqInput(\"GET\", Nil, Map(\"i0\" -> List(\"0\")), Map((\"Accept\", \"application/json\")))\n        api3(None).run[Id](cm) === ReqInput(\"GET\", Nil, Map.empty, Map((\"Accept\", \"application/json\")))\n      }\n\n      \"header\" >> {\n        val api0 = derive(:= :> Header[Int]('i0) :> Get[Json, ReqInput])\n        api0(0).run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"i0\" -> \"0\"))\n        val api1 = derive(:= :> Header[Int]('i0) :> Header[Int]('i1) :> Get[Json, ReqInput])\n        api1(0, 1).run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"i0\" -> \"0\", \"i1\" -> \"1\"))\n        val api2 = derive(:= :> Header[Option[Int]]('i0) :> Get[Json, ReqInput])\n        api2(Some(0)).run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"i0\" -> \"0\"))\n        api2(None).run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\"))\n        val api3 = derive(:= :> Header('i0, 'i1) :> Get[Json, ReqInput])\n        api3().run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"i0\" -> \"i1\"))\n        val api4 = derive(:= :> Client.Header[Int]('i0) :> Get[Json, ReqInput])\n        api4(0).run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"i0\" -> \"0\"))\n        val api5 = derive(:= :> Client.Header('i0, 'i1) :> Get[Json, ReqInput])\n        api5().run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"i0\" -> \"i1\"))\n        val api6 = derive(:= :> Client.Coll[Int] :> Get[Json, ReqInput])\n        api6(Map(\"hello\" -> 5)).run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"hello\" -> \"5\"))\n      }\n\n      \"ignore server elements\" >> {\n        val api0 = derive(:= :> Server.Match[String](\"Hello-\") :> Server.Send(\"a\", \"b\") :> Client.Header[Int]('i0) :> Get[Json, ReqInput])\n        api0(0).run[Id](cm) === ReqInput(\"GET\", Nil, Map(), Map(\"Accept\" -> \"application/json\", \"i0\" -> \"0\"))\n      }\n\n      \"request body\" >> {\n        val api0 = derive(:= :> ReqBody[Json, Int] :> Put[Json, ReqInputWithBody[Int]])\n        api0(0).run[Id](cm) === ReqInputWithBody(\"PUT\", Nil, Map(), Map((\"Accept\", \"application/json\")), 0)\n      }\n\n      \"path\" >> {\n        val api0 = derive(:= :> \"hello\" :> \"world\" :> Get[Json, ReqInput])\n        api0().run[Id](cm) === ReqInput(\"GET\", \"hello\" :: \"world\" :: Nil, Map(), Map((\"Accept\", \"application/json\")))\n      }\n    }\n\n    \"raw\" >> {\n      implicit def rawPutB[Bd] = testRawPutWithBody[Id, Bd](identity)\n\n      val api0 = derive(:= :> ReqBody[Json, Int] :> Put[Json, ReqInputWithBody[Int]])\n      api0(0).run[Id].raw(cm) === ReqInputWithBody(\"PUT\", Nil, Map(), Map((\"Accept\", \"application/json\")), 0)\n    }\n\n    \"composition\" >> {\n      val api = \n        (:= :> \"find\" :> Server.Match[String](\"Hello-\") :> Server.Send(\"a\", \"b\") :> Get[Json, ReqInput]) :|:\n        (:= :> \"fetch\" :> Segment[String]('type) :> Get[Json, ReqInput]) :|:\n        (:= :> \"store\" :> ReqBody[Json, Int] :> Post[Json, ReqInputWithBody[Int]])\n\n      val (find, fetch, store) = deriveAll(api)\n\n      find().run[Id](cm) === ReqInput(\"GET\", \"find\" :: Nil, Map(), Map((\"Accept\", \"application/json\")))\n      fetch(\"all\").run[Id](cm) === ReqInput(\"GET\", \"fetch\" :: \"all\" :: Nil, Map(), Map((\"Accept\", \"application/json\")))\n      store(0).run[Id](cm) === ReqInputWithBody(\"POST\", \"store\" :: Nil, Map(), Map((\"Accept\", \"application/json\")), 0)\n    }\n  }\n}\n"
  },
  {
    "path": "docs/ApiDefinition.md",
    "content": "## How to define an API\nThe central idea behind Typedapi is to make client and server implementation as boilerplate-free, typesafe and simple as possible.\n\n - On the client-side you only define what you expect from an API provided by a server. In other words, you define a contract between the client and the server.\n - The server-side then has to comply with that contract by implementing proper endpoint functions.\n \nBut how do you create this API definitions/contracts? This document will show you two ways provided by Typedapi:\n  - use the DSL (`import typedapi.dsl._`)\n  - or function-call-like definition (`import typedapi._`)\n \n### Base case\nEvery API has to fullfil the base case, meaning it has to have a root path and a method description:\n \n```Scala\n// dsl\n:= :> Get[MediaTypes.`application/json`, A]\n\n// or\n:= :> Get[MT.`application/json`, A]\n\n// or in case of JSON\n:= :> Get[Json, A]\n\n// function\napi(Get[Json, A])\n// or\napi(method = Get[Json, A], path = Root)\n```\n \nThis translates to `GET /` returning some `Json A`.\n\n### Methods\nSo far Typedapi supports the following methods:\n \n```Scala\n// dsl\n:= :> Get[Json, A]\n:= :> Put[Json, A]\n:= :> Post[Json, A]\n:= :> Delete[Json, A]\n\n// function\napi(Get[Json, A])\napi(Put[Json, A])\napi(Post[Json, A])\napi(Delete[Json, A])\n```\n \n### Request Body\nYou may noticed that `Put` and `Post` don't have a field to describe a request body. To add that you have to explicitly define it with an element in your Api:\n \n```Scala\n// PUT {body: User} /\n// dsl\n:= :> ReqBody[Json, B] :> Put[Json, A]\n\n// function\napiWithBody(Put[Json, A], ReqBody[Json, B])\n\n// POST {body: User} /\n// dsl\n:= :> ReqBody[Json, B] :> Post[Json, A]\n\n// function\napiWithBody(Post[Json, A], ReqBody[Json, B])\n```\n \nBy the way, you can only add `Put` and `Post` as the next element of `ReqBody`. Everything else will not compile. Thus, you end up with a valid API description and not something like `:= :> ReqBody[Json, B] :> Get[Json, A]` or `api(Get[Json, A], ReqBody[Json, B])`.\n\n### One word to encodings\nYou can find a list of provided encodings [here](https://github.com/pheymann/typedapi/blob/master/shared/src/main/scala/typedapi/shared/MediaTypes.scala). If you need something else implement `trait MediaType`.\n\n### Path\n```Scala\n// GET /hello/world\n// dsl\n:= :> \"hello\" :> \"world\" :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"hello\" / \"world\")\n```\n \nAll path elements are translated to singleton types and therefore encoded in the type of the API.\n \n### Segment\nHave a dynamic path element:\n \n```Scala\n// GET /user/{name: String}\n// dsl\n:= :> \"user\" :> Segment[String](\"name\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"user\" / Segment[String](\"name\"))\n```\n\nEvery segment gets a name which is again encoded as singleton type in the API type.\n\n### Query Parameter\n```Scala\n// GET /query?{id: Int}\n// dsl\n:= :> \"query\" :> Query[Int](\"id\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"query\", Queries.add[Int](\"id\"))\n```\n\nEvery query gets a name which is again encoded as singleton type in the API type.\n\n#### Optional Query\n```Scala\n// GET /query/opt?{id: Option[Int]}\n// dsl\n:= :> \"query\" :> \"opt\" :> Query[Option[Int]](\"id\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"query\" / \"opt\", Queries.add[Option[Int]](\"id\"))\n```\n\n#### Query with a List of elements\n```Scala\n// GET /query/list?{id: List[Int]}\n// dsl\n:= :> \"query\" :> \"list\" :> Query[List[Int]](\"id\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"query\" / \"list\", Queries.add[List[Int]](\"id\"))\n```\n\n### Header\n```Scala\n// GET /header {headers: id: Int}\n// dsl\n:= :> \"header\" :> Header[Int](\"id\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"header\", headers = Headers.add[Int](\"id\"))\n```\n\nThis header is an expected input parameter.\n\nEvery header gets a name which is again encoded as singleton type in the API type.\n\n#### Optional Header\n```Scala\n// GET /header/opt {headers: id: Option[Int]}\n// dsl\n:= :> \"header\" :> \"opt\" :> Header[Option[Int]](\"id\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"header\" / \"opt\", headers = Headers.add[Option[Int]](\"id\"))\n```\n\n#### Fixed Headers aka static headers\nIf you have a set of headers which are statically known and have to be provided by all sides you can add them as follows:\n\n```Scala\n// GET /header/fixed {headers: consumer=me}\n// dsl\n:= :> \"header\" :> \"fixed\" :> Header(\"consumer\", \"me\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"header\" / \"fixed\", headers = Headers.add(\"consumer\", \"me\"))\n```\n\n#### Client-Side: Headers\nYou have to send headers from the client-side but not server side? Here you go:\n\n```Scala\n// GET /header/client {header: consumer: String}\n// dsl\n:= :> \"header\" :> \"client\" :> Client.Header[String](\"consumer\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"header\" / \"client\", headers = Headers.client[String](\"consumer\"))\n```\n\n#### Client-Side: fixed/static Headers\nYou have to send static headers from the client-side but not server side? Here you go:\n\n```Scala\n// GET /header/client/fixed {header: consumer=me}\n// dsl\n:= :> \"header\" :> \"client\" :> \"fixed\" :> Client.Header(\"consumer\", \"me\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"header\" / \"client\" / \"fixed\", headers = Headers.client(\"consumer\", \"me\"))\n```\n\n#### Client-Side: Header collections\nYou can send header collections (`Map[String, V]`) as a single argument:\n\n```Scala\n// GET /header/client/coll {headers: a:b:...}\n//dsl\n:= :> \"header\" :> \"client\" :> \"coll\" :> Client.Coll[Int] :> Get[Json, A]\n\n//function\napi(Get[Json, A], Root / \"header\" / \"client\" / \"coll\", headers = Headers.clientColl[Int])\n```\n\n#### Server-Side: send Headers\nYou have to send headers from the server-side, e.g. for CORS? Here you go:\n\n```Scala\n// GET /header/server/send => {header: consumer=me}\n// dsl\n:= :> \"header\" :> \"server\" :> \"send\" :> Server.Send(\"consumer\", \"me\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"header\" / \"server\" / \"send\", headers = Headers.serverSend(\"consumer\", \"me\"))\n```\n\n#### Server-Side: extract matching Headers keys\nYou want to extract all headers which contain a certain `String`? Here you go:\n\n```Scala\n// GET /header/server/match {header: test1=me, test2=you}\n// dsl\n:= :> \"header\" :> \"server\" :> \"match\" :> Server.Match[String](\"test\") :> Get[Json, A]\n\n// function\napi(Get[Json, A], Root / \"header\" / \"server\" / \"match\", headers = Headers.serverMatch[String](\"test\"))\n```\n\nThis will give you a `Set[V]` with `V = String` in this example.\n\n### Multiple definitions in a single API\nYou can put multiple definitions into a single API element:\n\n```Scala\nval Api =\n  (:= :> \"hello\" :> Get[Json, A]) :|:\n  (:= :> \"world\" :> Query[Int]('foo) :> Delete[B])\n```\n"
  },
  {
    "path": "docs/ClientCreation.md",
    "content": "## Create a client from your API\nAfter we [defined](https://github.com/pheymann/typedapi/blob/master/docs/ApiDefinition.md) our API we have to derive a function/set of functions we can use to make our calls.\n\n```Scala\nval Api =\n  (api(Get[Json, User], Root / \"user\" / Segment[String](\"name\"))) :|:\n  (apiWithBody(Put[Json, User], ReqBody[Json, User], Root / \"user\"))\n```\n\n### First thing first, derive your functions\nLets derive our functions:\n\n```Scala\nimport typedapi.client._\n\nfinal case class User(name: String)\n\n// implicit encoders and decoders\n\nval (get, create) = deriveAll(Api)\n```\n\n### Http4s\nIf you want to use [http4s](https://github.com/http4s/http4s) as your client backend you have to add the following code:\n\n```Scala\nimport typedapi.client.http4s._\nimport org.http4s.client.blaze.Http1Client\n\nval client = Http1Client[IO]().unsafeRunSync\nval cm     = ClientManager(client, \"http://my-host\", myPort)\n```\n\n### Akka-Http\nIf you want to use [akka-http](https://github.com/akka/akka-http) as your client backend you have to add the following code:\n\n```Scala\nimport typedapi.client.akkahttp._\nimport akka.actor.ActorSystem\nimport akka.stream.ActorMaterializer\nimport akka.http.scaladsl.Http\n\nimplicit val timeout = 5.second\nimplicit val system  = ActorSystem(\"akka-http-client\")\nimplicit val mat     = ActorMaterializer()\n\nimport system.dispatcher\n\nval cm = ClientManager(Http(), \"http://my-host\", myPort)\n```\n\n### Scalaj-Http\nIf you want to use [scalaj-http](https://github.com/scalaj/scalaj-http) as your client backend you have to add the following code:\n\n```Scala\nimport typedapi.client.scalajhttp._\nimport scalaj.http._\n\nval cm = ClientManager(Http, \"http://my-host\", myPort)\n```\nBe aware that `typedapi.util` provides an `Encoder[F[_], A]` and `Decoder[F[_], A]` trait to marshall and unmarhsall bodies. You have to provide implementations for your types.\n\n```Scala\nimplicit val decoder = Decoder[Future, User] { json =>\n  // unmarshall the json using some known lib like circe\n}\n\nimplicit val encoder = Encoder[Future, User] { user =>\n  // marshall the user using some known lib like circe\n}\n```\n\n### Ammonite\nThere is special support for [Ammonite](http://ammonite.io/#Ammonite-REPL) and [ScalaScripts](http://ammonite.io/#ScalaScripts). It lets you tinker with the raw response and reduces the amount of imports you have to do:\n\n```Scala\nimport $ivy.`com.github.pheymann::typedapi-ammonite-client:<version>`\n\nimport typedapi._\nimport client._\nimport amm._\n\nval cm = clientManager(\"http://localhost\", 9000)\n\nfinal case class User(name: String, age: Int)\n\nval Api = api(Get[Json, User], Root / \"user\" / \"url\")\n\nval get = derive(Api)\n\n// gives you the raw scalaj-http response\nval response = get().run[Id].raw(cm)\n\nresponse.body\nresponse.headers\n...\n```\n\nNo `Decoder` needed if you use `raw(cm)`. Under the covers it uses scalaj-http as a client library.\n\nIt can be, that Ammonite isn't able to load `com.dwijnand:sbt-compat:1.0.0`. If that is the case execute the following command:\n\n```Scala\ninterp.repositories() ++= Seq(coursier.ivy.IvyRepository.fromPattern(\n  \"https://dl.bintray.com/dwijnand/sbt-plugins/\" +:\n  coursier.ivy.Pattern.default\n))\n```\n\n### ScalaJS\nIf you want to compile to [ScalaJS](https://www.scala-js.org/) you have to use the [Ajax](https://github.com/scala-js/scala-js-dom/blob/master/src/main/scala/org/scalajs/dom/ext/Extensions.scala#L253) with:\n\n```Scala\nimport typedapi.client.js._\nimport org.scalajs.dom.ext.Ajax\n\nval cm = ClientManager(Ajax, \"http://my-host\", myPort)\n```\n\nBe aware that `typedapi.util` provides an `Encoder[F[_], A]` and `Decoder[F[_], A]` trait to marshall and unmarhsall bodies. You have to provide implementations for your types.\n\n```Scala\nimplicit val decoder = Decoder[Future, User] { json =>\n  // unmarshall the json using some known lib like circe\n}\n\nimplicit val encoder = Encoder[Future, User] { user =>\n  // marshall the user using some known lib like circe\n}\n```\n\n### Usage\nNow we can to use our client functions:\n\n```Scala\nfor {\n  _    <- create(User(\"Joe\", 42)).run[IO](cm)\n  user <- get(\"Joe\").run[IO](cm)\n} yield user\n\n//F[User]\n```\n\n**Make sure** you have the proper encoders and decoders in place.\n"
  },
  {
    "path": "docs/ExtendIt.md",
    "content": "## Extend Typedapi to fit your needs\nYou ended up in this file if:\n - the default implements for a HTTP framework doesn't fit your needs\n - if the framework you want to use is not supported\n - you need more specilized [RequestDataBuilder](https://github.com/pheymann/typedapi/blob/master/client/src/main/scala/typedapi/client/RequestDataBuilder.scala), [RouteExtractors](https://github.com/pheymann/typedapi/blob/master/server/src/main/scala/typedapi/server/RouteExtractor.scala), [MediaTypes](https://github.com/pheymann/typedapi/blob/master/shared/src/main/scala/typedapi/shared/ApiElement.scala#L58), or the like\n\n### General remark\nI kept most of the type-classes open. That means you can override them as you like. If a certain class like *RequestDataBuilder* doesn't fullfil your needs just add another instance. Take a look at available implementations to get an idea how it works or ask a question in Gitter.\n\n### Write your own Client backend\nTo write your own client backend you have to implement the [ApiRequest](https://github.com/pheymann/typedapi/blob/master/client/src/main/scala/typedapi/client/ApiRequest.scala) type-classes:\n  - `GetRequest`\n  - `PutRequest` and `PutWithBodyRequest`\n  - `PostRequest` and `PostWithBodyRequest`\n  - `DeleteRequest`\n\nTake a look into [http4s-client](https://github.com/pheymann/typedapi/blob/master/http4s-client/src/main/scala/typedapi/client/http4s/package.scala) to get an idea how to do it.\n\nYou can implement all type-classes or just a subset to override implementations provided by TypedApi.\n\n### Write your own Server backend\nTo write your own server backend you have to implement the [EndpointExecutor](https://github.com/pheymann/typedapi/blob/master/server/src/main/scala/typedapi/server/EndpointExecutor.scala) and [MountEndpoints](https://github.com/pheymann/typedapi/blob/master/server/src/main/scala/typedapi/server/ServerManager.scala) type-classes\n\nTake a look into [http4s-server](https://github.com/pheymann/typedapi/blob/master/http4s-server/src/main/scala/typedapi/server/http4s/package.scala) to get an idea how to do it.\n\nYou can implement all type-classes or just a subset to override implementations provided by TypedApi.\n"
  },
  {
    "path": "docs/ServerCreation.md",
    "content": "## Create a server from your API\nAfter we [defined](https://github.com/pheymann/typedapi/blob/master/docs/ApiDefinition.md) our API we have to derive the endpoint/set of endpoints we can mount and serve to the world.\n\n```Scala\nval Api =\n  (api(Get[Json, User], Root / \"user\" / Segment[String](\"name\"))) :|:\n  (apiWithBody(Put[Json, User], ReqBody[Json, User], Root / \"user\"))\n```\n\n### First things first, derive the endpoints\n```Scala\nimport typedapi.server._\n\nfinal case class User(name: String)\n\n// implicit encoders and decoders\n\nval endpoints = deriveAll[IO](Api).from(\n  name => // retrieve and return user\n  user => // store user\n)\n```\n\n### Set Status Codes\n#### Success\n```Scala\nderiveAll[IO](Api).from(\n  name =>\n      val user: User = ???\n      \n      success(user) // creates a 200\n  ...\n}\n```\n\nor\n\n```Scala\nderiveAll[IO](Api).from(\n  name =>\n      val user: User = ???\n      \n      successWith(StatusCodes.Ok)(user) // set code\n  ...\n}\n```\n\n#### Error\n```Scala\nderiveAll[IO](Api).from(\n  name =>\n      val user: Option[User] = ???\n      \n      user.fold(errorWith(StatusCodes.NotFound, s\"no user $id\")(user => success(user))\n  ...\n}\n```\n\n### Http4s\nIf you want to use [http4s](https://github.com/http4s/http4s) as your server backend you have to add the following code:\n\n```Scala\nimport typedapi.server.http4s._\nimport org.http4s.server.blaze.BlazeBuilder\n\nval sm = ServerManager(BlazeBuilder[IO], \"http://my-host\", myPort)\n```\n\n### Akka-Http\nIf you want to use [akka-http](https://github.com/akka/akka-http) as your server backend you have to add the following code:\n\n```Scala\nimplicit val timeout = 5.second\nimplicit val system  = ActorSystem(\"akka-http-server\")\nimplicit val mat     = ActorMaterializer()\n\nimport system.dispatcher\n    \nval sm = ServerManager(Http(), \"http://my-host\", myPort)\n```\n\n### Start server\nNow we can mount `endpoints` and serve to to the world:\n\n```Scala\nval server = mount(sm, endpoints)\n\nserver.unsafeRunSync()\n```\n\n**Make sure** you have the proper encoders and decoders in place.\n"
  },
  {
    "path": "docs/example/ammonite_client_example.sc",
    "content": "import $ivy.`com.github.pheymann::typedapi-ammonite-client:0.2.0-M1`\n\nimport typedapi._\nimport client._\nimport amm._\n\nval cm = clientManager(\"http://localhost\", 9000)\n\nfinal case class User(name: String, age: Int)\n\nval Api = api(Get[Json, User], Root, headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\"))\n\nval get = derive(Api)\n\nval response = get().run[Id].raw(cm)\n"
  },
  {
    "path": "docs/example/build.sbt",
    "content": "\nval typedapiVersion = \"0.2.0\"\nval http4sVersion   = \"0.18.0\"\n\nval commonSettings = Seq(\n  scalaVersion := \"2.12.4\"\n)\n\nlazy val root = project\n  .in(file(\".\"))\n  .aggregate(`shared-jvm`, `shared-js`, `client-jvm`, `client-js`, server)\n\nlazy val shared = crossProject.crossType(CrossType.Pure)\n  .in(file(\"shared\"))\n  .settings(commonSettings: _*)\n  .settings(\n    libraryDependencies ++= Seq(\n      \"com.github.pheymann\" %%% \"typedapi-shared\" % typedapiVersion,\n\n      \"io.circe\" %%% \"circe-core\" % \"0.9.1\",\n      \"io.circe\" %%% \"circe-parser\" % \"0.9.1\",\n      \"io.circe\" %%% \"circe-generic\" % \"0.9.1\"\n    )\n  )\n\nlazy val `shared-js` = shared.js\nlazy val `shared-jvm` = shared.jvm\n\nlazy val server = project\n  .in(file(\"server\"))\n  .settings(commonSettings: _*)\n  .settings(\n    libraryDependencies ++= Seq(\n      \"com.github.pheymann\" %% \"typedapi-http4s-server\" % typedapiVersion,\n\n      \"org.http4s\" %% \"http4s-circe\" % http4sVersion,\n      \"org.http4s\" %% \"http4s-blaze-server\" % http4sVersion,\n      \"org.http4s\" %% \"http4s-dsl\" % http4sVersion\n    )\n  )\n  .dependsOn(`shared-jvm`)\n\nlazy val `client-jvm` = project\n  .in(file(\"client-jvm\"))\n  .settings(commonSettings: _*)\n  .settings(\n    libraryDependencies ++= Seq(\n      \"com.github.pheymann\" %% \"typedapi-http4s-client\" % typedapiVersion,\n\n      \"org.http4s\" %% \"http4s-circe\" % http4sVersion,\n      \"org.http4s\" %% \"http4s-blaze-client\" % http4sVersion,\n      \"org.http4s\" %% \"http4s-dsl\" % http4sVersion\n    )\n  )\n  .dependsOn(`shared-jvm`)\n\nlazy val `client-js` = project\n  .in(file(\"client-js\"))\n  .enablePlugins(ScalaJSPlugin)\n  .settings(commonSettings: _*)\n  .settings(\n    libraryDependencies ++= Seq(\n      \"com.github.pheymann\" %%% \"typedapi-js-client\" % typedapiVersion,\n    ),\n    scalaJSUseMainModuleInitializer := true\n  )\n  .dependsOn(`shared-js`)\n"
  },
  {
    "path": "docs/example/client-js/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <body>\n    <script src=\"target/scala-2.12/client-js-fastopt.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/example/client-js/src/main/scala/Client.scala",
    "content": "\nimport typedapi.client._\nimport typedapi.client.js._\nimport org.scalajs.dom.ext.Ajax\nimport io.circe._\nimport io.circe.generic.auto._\nimport io.circe.parser._\nimport io.circe.syntax._\n\nimport scala.concurrent.Future\nimport scala.concurrent.ExecutionContext.Implicits.global\nimport scala.concurrent.duration._\n\nobject Client {\n\n  type Id[A] = A\n\n  final case class DecodeException(msg: String) extends Exception\n\n  implicit val decoder = typedapi.util.Decoder[Future, User](json => decode[User](json).fold(\n    error => Future.successful(Left(DecodeException(error.toString()))), \n    user  => Future.successful(Right(user))\n  ))\n  implicit val encoder = typedapi.util.Encoder[Future, User](user => Future.successful(user.asJson.noSpaces))\n\n  val (get, put, post, delete, path, putBody, segment, search, header, fixed, client, coll, matches) = deriveAll(FromDsl.MyApi)\n\n  def main(args: Array[String]): Unit = {\n    val cm = ClientManager(Ajax, \"http://localhost\", 9000)\n\n    (for {\n      u0 <- putBody(User(\"joe\", 27)).run[Future](cm)\n      u1 <- search(\"joe\").run[Future](cm)\n    } yield (u0, u1)).foreach { case (u0, u1) =>\n      println(u0)\n      println(u1)\n    }\n  }\n}\n"
  },
  {
    "path": "docs/example/client-jvm/src/main/scala/Client.scala",
    "content": "\nimport typedapi.client._\nimport typedapi.client.http4s._\nimport cats.effect.IO\nimport org.http4s._\nimport org.http4s.circe._\n\nobject Client {\n\n  implicit val decoder = jsonOf[IO, User]\n  implicit val encoder = jsonEncoderOf[IO, User]\n\n  val (get, put, post, delete, path, putBody, segment, search, header, fixed, client, coll, matches) = deriveAll(FromDsl.MyApi)\n\n  def main(args: Array[String]): Unit = {\n    import User._\n    import cats.effect.IO\n    import org.http4s.client.blaze.Http1Client\n\n    val cm = ClientManager(Http1Client[IO]().unsafeRunSync, \"http://localhost\", 9000)\n\n    (for {\n      u0 <- putBody(User(\"joe\", 27)).run[IO](cm)\n      u1 <- search(\"joe\").run[IO](cm)\n    } yield {\n      println(u0)\n      println(u1)\n      ()\n    }).unsafeRunSync()\n  }\n}\n"
  },
  {
    "path": "docs/example/project/build.properties",
    "content": "sbt.version=1.0.4"
  },
  {
    "path": "docs/example/project/plugins.sbt",
    "content": "addSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % \"0.6.22\")\n"
  },
  {
    "path": "docs/example/server/src/main/scala/Server.scala",
    "content": "\nimport typedapi.server._\nimport typedapi.server.http4s._\nimport cats.effect.IO\nimport org.http4s._\nimport org.http4s.circe._\n\nobject Server {\n\n  implicit val decoder = jsonOf[IO, User]\n  implicit val encoder = jsonEncoderOf[IO, User]\n\n  val get: () => IO[Result[User]] = () => IO.pure(success(User(\"Joe\", 42)))\n  val put: () => IO[Result[User]] = get\n  val post: () => IO[Result[User]] = get\n  val delete: () => IO[Result[User]] = get\n\n  val path: () => IO[Result[User]] = get\n\n  val putBody: User => IO[Result[User]] = user => IO.pure(success(user))\n  val segment: String => IO[Result[User]] = name => IO.pure(success(User(name, 42)))\n  val search: String => IO[Result[User]] = segment\n\n  val header: String => IO[Result[User]] = consumer => IO.pure(success(User(\"found: \" + consumer, 42)))\n  val fixed: () => IO[Result[User]] = get\n  val client: () => IO[Result[User]] = get\n  val coll: () => IO[Result[User]] = get\n  val matching: Map[String, String] => IO[Result[User]] = matches => IO.pure(success(User(matches.mkString(\",\"), 42)))\n\n  val endpoints = deriveAll[IO](FromDefinition.MyApi).from(\n    get, \n    put, \n    post, \n    delete, \n    path, \n    putBody, \n    segment, \n    search, \n    header, \n    fixed, \n    client, \n    coll, \n    matching\n  )\n\n  def main(args: Array[String]): Unit = {\n    import org.http4s.server.blaze.BlazeBuilder\n\n    val sm = ServerManager(BlazeBuilder[IO], \"localhost\", 9000)\n\n    mount(sm, endpoints).unsafeRunSync()\n\n    scala.io.StdIn.readLine(\"Press 'Enter' to stop ...\")\n  }\n}\n"
  },
  {
    "path": "docs/example/shared/src/main/scala/Apis.scala",
    "content": "\nobject FromDsl {\n\n  import typedapi.dsl._\n\n  /* NOTE: we have to add the 'Access-Control-Allow-Origin' header to the server-side to allow the \n   * browser (ScalaJS) to access the server (CORS)\n   */\n\n  val MyApi = \n    // basic GET request\n    (:= :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    // basic PUT request\n    (:= :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Put[Json, User]) :|:\n    // basic POST request\n    (:= :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Post[Json, User]) :|:\n    // basic DELETE request\n    (:= :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Delete[Json, User]) :|:\n    // define a path\n    (:= :> \"my\" :> \"path\" :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    // add a request body\n    (:= :> \"with\" :> \"body\" :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> ReqBody[Json, User] :> Put[Json, User]) :|:\n    // add segments\n    (:= :> \"name\" :> Segment[String](\"name\") :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    // add query\n    (:= :> \"search\" :> \"user\" :> Query[String](\"name\") :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    // add header\n    (:= :> \"header\" :> Header[String](\"consumer\") :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"fixed\" :> Header(\"consumer\", \"me\") :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"client\" :> Client.Header(\"client\", \"me\") :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"client\" :> \"coll\" :> Client.Coll[Int] :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"server\" :> Server.Match[String](\"Control-\") :> Server.Send(\"Access-Control-Allow-Origin\", \"*\") :> Get[Json, User])\n}\n\nobject FromDefinition {\n\n  import typedapi._\n\n  val MyApi =\n    // basic GET request\n    api(Get[Json, User], headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // basic PUT request\n    api(Put[Json, User], headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // basic POST request\n    api(Post[Json, User], headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // basic Delete request\n    api(Delete[Json, User], headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // define a path\n    api(Get[Json, User], Root / \"my\" / \"path\", headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // add a request body\n    apiWithBody(Put[Json, User], ReqBody[Json, User], Root / \"with\" / \"body\", headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // add segments\n    api(Get[Json, User], Root / \"name\" / Segment[String](\"name\"), headers = Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // add query\n    api(Get[Json, User], Root / \"search\" / \"user\", Queries.add[String](\"name\"), Headers.serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    // add header\n    api(Get[Json, User], Root / \"header\", headers = Headers.add[String](\"consumer\").serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    api(Get[Json, User], Root / \"header\" / \"fixed\", headers = Headers.add(\"consumer\", \"me\").serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    api(Get[Json, User], Root / \"header\" / \"client\", headers = Headers.client(\"client\", \"me\").serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    api(Get[Json, User], Root / \"header\" / \"client\" / \"coll\", headers = Headers.clientColl[Int].serverSend(\"Access-Control-Allow-Origin\", \"*\")) :|:\n    api(Get[Json, User], Root / \"header\" / \"server\", headers = Headers.serverMatch[String](\"Control-\").serverSend(\"Access-Control-Allow-Origin\", \"*\"))\n}\n"
  },
  {
    "path": "docs/example/shared/src/main/scala/User.scala",
    "content": "\nimport io.circe.syntax._\nimport io.circe.generic.JsonCodec\n\nfinal case class User(name: String, age: Int)\n\nobject User {\n\n  implicit val enc = io.circe.generic.semiauto.deriveEncoder[User]\n  implicit val dec = io.circe.generic.semiauto.deriveDecoder[User]\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/User.scala",
    "content": "package http.support.tests\n\nimport cats.effect.IO\nimport io.circe.generic.semiauto._\nimport org.http4s.circe._\nimport org.http4s.dsl.io._\n\nfinal case class User(name: String, age: Int)\n\nobject UserCoding {\n\n  implicit val enc = deriveEncoder[User]\n  implicit val dec = deriveDecoder[User]\n\n  implicit val decoderIO = jsonOf[IO, User]\n  implicit val encoderIO = jsonEncoderOf[IO, User]\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/client/AkkaHttpClientSupportSpec.scala",
    "content": "package http.support.tests.client\n\nimport http.support.tests.{User, UserCoding, Api}\nimport typedapi.client._\nimport typedapi.client.akkahttp._\nimport akka.actor.ActorSystem\nimport akka.stream.ActorMaterializer\nimport akka.http.scaladsl.Http\nimport de.heikoseeberger.akkahttpcirce.FailFastCirceSupport\nimport org.specs2.mutable.Specification\nimport org.specs2.concurrent.ExecutionEnv\n\nimport scala.concurrent.duration._\nimport scala.concurrent.{Future, Await}\n\nfinal class AkkaHttpClientSupportSpec(implicit ee: ExecutionEnv) extends Specification {\n\n  import UserCoding._\n  import FailFastCirceSupport._\n\n  sequential\n\n  implicit val timeout = 5.second\n  implicit val system  = ActorSystem(\"akka-http-client-spec\", defaultExecutionContext = Some(ee.ec))\n  implicit val mat     = ActorMaterializer()\n\n  import system.dispatcher\n\n  val cm     = ClientManager(Http(), \"http://localhost\", 9001)\n  val server = TestServer.start()\n\n  \"akka http client support\" >> {\n    val (p, s, q, header, fixed, clInH, clFixH, clColl, serMatchH, serSendH, m0, m1, m2, m3, m4, m5, _, _, _) = deriveAll(Api)\n\n    \"paths and segments\" >> {\n      p().run[Future](cm) must beEqualTo(User(\"foo\", 27)).awaitFor(timeout)\n      s(\"jim\").run[Future](cm) must beEqualTo(User(\"jim\", 27)).awaitFor(timeout)\n    }\n    \n    \"queries\" >> {\n      q(42).run[Future](cm) must beEqualTo(User(\"foo\", 42)).awaitFor(timeout)\n    }\n    \n    \"headers\" >> {\n      header(42).run[Future](cm) must beEqualTo(User(\"foo\", 42)).awaitFor(timeout)\n      fixed().run[Future](cm) must beEqualTo(User(\"joe\", 27)).awaitFor(timeout)\n      clInH(\"jim\").run[Future](cm) must beEqualTo(User(\"jim\", 27)).awaitFor(timeout)\n      clFixH().run[Future](cm) must beEqualTo(User(\"joe\", 27)).awaitFor(timeout)\n      clColl(Map(\"coll\" -> \"joe\", \"collect\" -> \"jim\")).run[Future](cm) must beEqualTo(User(\"coll: joe,collect: jim\", 27)).awaitFor(timeout)\n      serMatchH().run[Future](cm) must beEqualTo(User(\"joe\", 27)).awaitFor(timeout)\n      serSendH().run[Future](cm) must beEqualTo(User(\"joe\", 27)).awaitFor(timeout)\n    }\n\n    \"methods\" >> {\n      m0().run[Future](cm) must beEqualTo(User(\"foo\", 27)).awaitFor(timeout)\n      m1().run[Future](cm) must beEqualTo(User(\"foo\", 27)).awaitFor(timeout)\n      m2(User(\"jim\", 42)).run[Future](cm) must beEqualTo(User(\"jim\", 42)).awaitFor(timeout)\n      m3().run[Future](cm) must beEqualTo(User(\"foo\", 27)).awaitFor(timeout)\n      m4(User(\"jim\", 42)).run[Future](cm) must beEqualTo(User(\"jim\", 42)).awaitFor(timeout)\n      m5(List(\"because\")).run[Future](cm) must beEqualTo(User(\"foo\", 27)).awaitFor(timeout)\n    }\n\n    step {\n      server.shutdown.unsafeRunSync()\n      Await.ready(system.terminate, timeout)\n    }\n  }\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/client/Http4sClientSupportSpec.scala",
    "content": "package http.support.tests.client\n\nimport http.support.tests.{UserCoding, User, Api}\nimport typedapi.client._\nimport typedapi.client.http4s._\nimport cats.effect.IO\nimport org.http4s.client.blaze.Http1Client\nimport org.specs2.mutable.Specification\n\nfinal class Http4sClientSupportSpec extends Specification {\n\n  import UserCoding._\n\n  sequential\n\n  val cm = ClientManager(Http1Client[IO]().unsafeRunSync, \"http://localhost\", 9001)\n\n  val server = TestServer.start()\n\n  \"http4s client support\" >> {\n    val (p, s, q, header, fixed, clInH, clFixH, clColl, serMatchH, serSendH, m0, m1, m2, m3, m4, m5, _, _, _) = deriveAll(Api)\n\n    \"paths and segments\" >> {\n      p().run[IO](cm).unsafeRunSync() === User(\"foo\", 27)\n      s(\"jim\").run[IO](cm).unsafeRunSync() === User(\"jim\", 27)\n    }\n    \n    \"queries\" >> {\n      q(42).run[IO](cm).unsafeRunSync() === User(\"foo\", 42)\n    }\n    \n    \"headers\" >> {\n      header(42).run[IO](cm).unsafeRunSync() === User(\"foo\", 42)\n      fixed().run[IO](cm).unsafeRunSync() === User(\"joe\", 27)\n      clInH(\"jim\").run[IO](cm).unsafeRunSync === User(\"jim\", 27)\n      clFixH().run[IO](cm).unsafeRunSync() === User(\"joe\", 27)\n      clColl(Map(\"coll\" -> \"joe\", \"collect\" -> \"jim\")).run[IO](cm).unsafeRunSync === User(\"coll: joe,collect: jim\", 27)\n      serMatchH().run[IO](cm).unsafeRunSync() === User(\"joe\", 27)\n      serSendH().run[IO](cm).unsafeRunSync() === User(\"joe\", 27)\n    }\n\n    \"methods\" >> {\n      m0().run[IO](cm).unsafeRunSync() === User(\"foo\", 27)\n      m1().run[IO](cm).unsafeRunSync() === User(\"foo\", 27)\n      m2(User(\"jim\", 42)).run[IO](cm).unsafeRunSync() === User(\"jim\", 42)\n      m3().run[IO](cm).unsafeRunSync() === User(\"foo\", 27)\n      m4(User(\"jim\", 42)).run[IO](cm).unsafeRunSync() === User(\"jim\", 42)\n      m5(List(\"because\")).run[IO](cm).unsafeRunSync() === User(\"foo\", 27)\n    }\n\n    step {\n      server.shutdown.unsafeRunSync()\n    }\n  }\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/client/ScalajHttpClientSupportSpec.scala",
    "content": "package http.support.tests.client\n\nimport http.support.tests.{UserCoding, User, Api}\nimport typedapi.client._\nimport typedapi.client.scalajhttp._\nimport scalaj.http.Http\nimport io.circe.parser._\nimport io.circe.syntax._\nimport org.specs2.mutable.Specification\n\nfinal class ScalajHttpClientSupportSpec extends Specification {\n\n  import UserCoding._\n\n  sequential\n\n  case class DecodeException(msg: String) extends Exception\n\n  implicit val decoder = typedapi.util.Decoder[Id, User](json => decode[User](json).fold(\n    error => Left(DecodeException(error.toString())),\n    user  => Right(user)\n  ))\n  implicit val encoder = typedapi.util.Encoder[Id, User](user => user.asJson.noSpaces)\n\n  val cm = ClientManager(Http, \"http://localhost\", 9001)\n\n  val server = TestServer.start()\n\n  \"http4s client support\" >> {\n    val (p, s, q, header, fixed, clInH, clFixH, clColl, serMatchH, serSendH, m0, m1, m2, m3, m4, m5, _, _, _) = deriveAll(Api)\n\n    \"paths and segments\" >> {\n      p().run[Blocking](cm) === Right(User(\"foo\", 27))\n      s(\"jim\").run[Blocking](cm) === Right(User(\"jim\", 27))\n    }\n    \n    \"queries\" >> {\n      q(42).run[Blocking](cm) === Right(User(\"foo\", 42))\n    }\n    \n    \"headers\" >> {\n      header(42).run[Blocking](cm) === Right(User(\"foo\", 42))\n      fixed().run[Blocking](cm) === Right(User(\"joe\", 27))\n      clInH(\"jim\").run[Blocking](cm) === Right(User(\"jim\", 27))\n      clFixH().run[Blocking](cm) === Right(User(\"joe\", 27))\n      clColl(Map(\"coll\" -> \"joe\", \"collect\" -> \"jim\")).run[Blocking](cm) === Right(User(\"collect: jim,coll: joe\", 27))\n      serMatchH().run[Blocking](cm) === Right(User(\"joe\", 27))\n      serSendH().run[Blocking](cm) === Right(User(\"joe\", 27))\n    }\n\n    \"methods\" >> {\n      m0().run[Blocking](cm) === Right(User(\"foo\", 27))\n      m1().run[Blocking](cm) === Right(User(\"foo\", 27))\n      m2(User(\"jim\", 42)).run[Blocking](cm) === Right(User(\"jim\", 42))\n      m3().run[Blocking](cm) === Right(User(\"foo\", 27))\n      m4(User(\"jim\", 42)).run[Blocking](cm) === Right(User(\"jim\", 42))\n      m5(List(\"because\")).run[Blocking](cm) === Right(User(\"foo\", 27))\n    }\n\n    \"raw\" >> {\n      m0().run[Id].raw(cm).body === \"\"\"{\"name\":\"foo\",\"age\":27}\"\"\"\n    }\n\n    step {\n      server.shutdown.unsafeRunSync()\n    }\n  }\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/client/TestServer.scala",
    "content": "package http.support.tests.client\n\nimport http.support.tests.{User, UserCoding}\nimport cats.effect.IO\nimport io.circe.syntax._\nimport org.http4s._\nimport org.http4s.circe._\nimport org.http4s.dsl.io._\nimport org.http4s.server.Server\nimport org.http4s.server.blaze._\n\nobject Age extends QueryParamDecoderMatcher[Int](\"age\")\n\nobject Reasons {\n  def unapplySeq(params: Map[String, Seq[String]]) = params.get(\"reasons\")\n  def unapply(params: Map[String, Seq[String]]) = unapplySeq(params)\n}\n\nobject TestServer {\n\n  import UserCoding._\n   \n  val service = HttpService[IO] {\n    case GET -> Root / \"path\" => Ok(User(\"foo\", 27))\n    case GET -> Root / \"segment\" / name => Ok(User(name, 27))\n\n    case GET -> Root / \"query\" :? Age(age) => Ok(User(\"foo\", age))\n\n    case req @ GET -> Root / \"header\" => \n      val headers = req.headers.toList\n      val age     = headers.find(_.name.value == \"age\").get.value.toInt\n\n      Ok(User(\"foo\", age))\n\n    case req @ GET -> Root / \"header\" / \"fixed\" => \n      val headers = req.headers.toList\n      val value   = headers.find(_.name.value == \"Hello\").get.value\n\n      if (value != \"*\")\n        throw new IllegalArgumentException(\"unexpected header value \" + value)\n\n      Ok(User(\"joe\", 27))\n\n    case req @ GET -> Root / \"header\" / \"client\" =>\n      val headers = req.headers.toList\n      val value   = headers.find(_.name.value == \"Hello\").get.value\n\n      if (value != \"*\")\n        throw new IllegalArgumentException(\"unexpected header value \" + value)\n\n      Ok(User(\"joe\", 27))\n\n    case req @ GET -> Root / \"header\" / \"client\" / \"coll\" =>\n      val headers = req.headers.toList\n      val values  = headers.filter(_.name.value.contains(\"coll\"))\n\n      if (values.isEmpty)\n        throw new IllegalArgumentException(\"no header collection \")\n\n      Ok(User(values.mkString(\",\"), 27))\n\n    case req @ GET -> Root / \"header\" / \"input\" / \"client\" =>\n      val headers = req.headers.toList\n      val value   = headers.find(_.name.value == \"Hello\").get.value\n\n      Ok(User(value, 27))\n\n    case req @ GET -> Root / \"header\" / \"server\" / \"send\" =>\n      Ok(User(\"joe\", 27)).map(resp => resp.copy(headers = resp.headers put Header(\"Hello\", \"*\")))\n\n    case req @ GET -> Root / \"header\" / \"server\" / \"match\" =>\n      Ok(User(\"joe\", 27))\n\n    case GET -> Root => Ok(User(\"foo\", 27))\n    case PUT -> Root => Ok(User(\"foo\", 27))\n    case req @ PUT -> Root / \"body\" => Ok(User(\"foo\", 27))\n      for {\n        user <- req.as[User]\n        resp <- Ok(user.asJson)\n      } yield resp\n\n    case POST -> Root => Ok(User(\"foo\", 27))\n    case req @ POST -> Root / \"body\" => Ok(User(\"foo\", 27))\n      for {\n        user <- req.as[User]\n        resp <- Ok(user.asJson)\n      } yield resp\n\n    case DELETE -> Root :? Reasons(reasons) => \n      println(reasons)\n      Ok(User(\"foo\", 27))\n  }\n\n  def start(): Server[IO] = {\n    val builder = BlazeBuilder[IO]\n      .bindHttp(9001, \"localhost\")\n      .mountService(service, \"/\")\n      .start\n\n    builder.unsafeRunSync()\n  }\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/package.scala",
    "content": "package http.support\n\nimport typedapi.dsl._\n\npackage object tests {\n\n  val Api =\n    (:= :> \"path\" :> Get[Json, User]) :|:\n    (:= :> \"segment\" :> Segment[String]('name) :> Get[Json, User]) :|:\n    (:= :> \"query\" :> Query[Int]('age) :> Get[Json, User]) :|:\n    (:= :> \"header\" :> Header[Int]('age) :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"fixed\" :> Header(\"Hello\", \"*\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"input\" :> \"client\" :> Client.Header[String](\"Hello\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"client\" :> Client.Header(\"Hello\", \"*\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"client\" :> \"coll\" :> Client.Coll[String] :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"server\" :> \"match\" :> Server.Match[String](\"test\") :> Get[Json, User]) :|:\n    (:= :> \"header\" :> \"server\" :> \"send\" :> Server.Send(\"Hello\", \"*\") :> Get[Json, User]) :|:\n    (:= :> Get[Json, User]) :|:\n    (:= :> Put[Json, User]) :|:\n    (:= :> \"body\" :> ReqBody[Json, User] :> Put[Json, User]) :|:\n    (:= :> Post[Json, User]) :|:\n    (:= :> \"body\" :> ReqBody[Json, User] :> Post[Json, User]) :|:\n    (:= :> Query[List[String]]('reasons) :> Delete[Json, User]) :|:\n    (:= :> \"status\" :> \"200\" :> Get[Plain, String]) :|:\n    (:= :> \"status\" :> \"400\" :> Get[Plain, String]) :|:\n    (:= :> \"status\" :> \"500\" :> Get[Plain, String])\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/server/AkkaHttpServerSupportSpec.scala",
    "content": "package http.support.tests.server\n\nimport http.support.tests.{Api, UserCoding}\nimport typedapi.server._\nimport typedapi.server.akkahttp._\nimport akka.actor.ActorSystem\nimport akka.stream.ActorMaterializer\nimport akka.http.scaladsl.Http\nimport de.heikoseeberger.akkahttpcirce.FailFastCirceSupport\nimport cats.implicits._\nimport org.specs2.concurrent.ExecutionEnv\n\nimport scala.concurrent.{Future, Await}\nimport scala.concurrent.duration._\n\nfinal class AkkaHttpServerSupportSpec(implicit ee: ExecutionEnv) extends ServerSupportSpec[Future]()(catsStdInstancesForFuture(ee.ec)) {\n\n  import UserCoding._\n  import FailFastCirceSupport._\n\n  implicit val timeout = 5.second\n  implicit val system  = ActorSystem(\"akka-http-server-spec\", defaultExecutionContext = Some(ee.ec))\n  implicit val mat     = ActorMaterializer()\n\n  import system.dispatcher\n\n  val endpoints = deriveAll[Future](Api).from(\n    path, \n    segment, \n    query, \n    header, \n    fixed, \n    input, \n    clientHdr,\n    coll,\n    matching, \n    send, \n    get, \n    put, \n    putB, \n    post, \n    postB, \n    delete, \n    code200, \n    code400, \n    code500\n  )\n  val sm        = ServerManager(Http(), \"localhost\", 9000)\n  val server    = mount(sm, endpoints)\n\n  \"akka http implements TypedApi's server interface\" >> {\n    tests(9000)\n\n    step {\n      Await.ready(server.map(_.unbind()), timeout)\n      Await.ready(system.terminate, timeout)\n    }\n  }\n\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/server/Http4sServerSupportSpec.scala",
    "content": "package http.support.tests.server\n\nimport http.support.tests.{UserCoding, Api}\nimport typedapi.server._\nimport typedapi.server.http4s._\nimport cats.effect.IO\nimport org.http4s.server.blaze.BlazeBuilder\n\nfinal class Http4sServerSupportSpec extends ServerSupportSpec[IO] {\n\n  import UserCoding._\n\n  val endpoints = deriveAll[IO](Api).from(\n    path, \n    segment, \n    query, \n    header, \n    fixed, \n    input, \n    clientHdr,\n    coll,\n    matching, \n    send, \n    get, \n    put, \n    putB, \n    post, \n    postB, \n    delete, \n    code200, \n    code400, \n    code500\n  )\n  val sm        = ServerManager(BlazeBuilder[IO], \"localhost\", 9000)\n  val server    = mount(sm, endpoints).unsafeRunSync()\n\n  \"http4s implements TypedApi's server interface\" >> {\n    tests(9000)\n\n    step {\n      server.shutdown.unsafeRunSync()\n    }\n  }\n\n}\n"
  },
  {
    "path": "http-support-tests/src/test/scala/http/support/tests/server/ServerSupportSpec.scala",
    "content": "package http.support.tests.server\n\nimport typedapi.server._\nimport http.support.tests.{User, UserCoding}\nimport org.http4s._\nimport org.http4s.dsl.io._\nimport org.http4s.client.blaze._\nimport org.http4s.client.dsl.io._\nimport cats.Applicative\nimport cats.effect.IO\nimport org.specs2.mutable.Specification\n\nimport scala.language.higherKinds\n\nabstract class ServerSupportSpec[F[_]: Applicative] extends Specification {\n\n  import StatusCodes._\n\n  sequential\n\n  val client = Http1Client[IO]().unsafeRunSync\n\n  def tests(port: Int) = {\n    import UserCoding._\n\n    \"paths and segments\" >> {\n      client.expect[User](s\"http://localhost:$port/path\").unsafeRunSync() === User(\"path\", 27)\n      client.expect[User](s\"http://localhost:$port/segment/jim\").unsafeRunSync() === User(\"jim\", 27)\n    }\n\n    \"queries\" >> {\n      client.expect[User](s\"http://localhost:$port/query?age=42\").unsafeRunSync() === User(\"query\", 42)\n    }\n\n    \"headers\" >> {\n      client.expect[User](Request[IO](\n        method = GET,\n        uri = Uri.fromString(s\"http://localhost:$port/header\").right.get,\n        headers = Headers(Header(\"age\", \"42\"))\n      )).unsafeRunSync() === User(\"header\", 42)\n      client.expect[User](Request[IO](\n        method = GET,\n        uri = Uri.fromString(s\"http://localhost:$port/header/fixed\").right.get,\n        headers = Headers(Header(\"Hello\", \"*\"))\n      )).unsafeRunSync() === User(\"fixed\", 27)\n      client.expect[User](Request[IO](\n        method = GET,\n        uri = Uri.fromString(s\"http://localhost:$port/header/client\").right.get\n      )).unsafeRunSync() === User(\"client header\", 27)\n      client.expect[User](Request[IO](\n        method = GET,\n        uri = Uri.fromString(s\"http://localhost:$port/header/input/client\").right.get\n      )).unsafeRunSync() === User(\"input\", 27)\n      client.fetch[Option[Header]](\n        Request[IO](\n          method = GET,\n          uri = Uri.fromString(s\"http://localhost:$port/header/server/send\").right.get\n        )\n      )(\n        resp => IO {\n          resp.headers.toList.find(_.name.toString == \"Hello\")\n        }\n      ).unsafeRunSync() === Some(Header(\"Hello\", \"*\"))\n      client.expect[User](Request[IO](\n        method = GET,\n        uri = Uri.fromString(s\"http://localhost:$port/header/server/match\").right.get,\n        headers = Headers(Header(\"test\", \"foo\"), Header(\"testy\", \"bar\"), Header(\"meh\", \"NONO\"))\n      )).unsafeRunSync() === User(\"test -> foo,testy -> bar\", 27)\n      client.fetch[Option[Header]](\n        Request[IO](\n          method = OPTIONS,\n          uri = Uri.fromString(s\"http://localhost:$port/header/fixed\").right.get,\n          headers = Headers(Header(\"Hello\", \"*\"))\n        )\n      )(\n        resp => IO {\n          resp.headers.toList.find(_.name.toString == \"Access-Control-Allow-Methods\")\n        }\n      ).unsafeRunSync() === Some(Header(\"Access-Control-Allow-Methods\", \"GET\"))\n    }\n\n    \"methods\" >> {\n      client.expect[User](s\"http://localhost:$port/\").unsafeRunSync() === User(\"get\", 27)\n      client.expect[User](PUT(Uri.fromString(s\"http://localhost:$port/\").right.get)).unsafeRunSync() === User(\"put\", 27)\n      client.expect[User](PUT(Uri.fromString(s\"http://localhost:$port/body\").right.get, User(\"joe\", 27))).unsafeRunSync() === User(\"joe\", 27)\n      client.expect[User](POST(Uri.fromString(s\"http://localhost:$port/\").right.get)).unsafeRunSync() === User(\"post\", 27)\n      client.expect[User](POST(Uri.fromString(s\"http://localhost:$port/body\").right.get, User(\"joe\", 27))).unsafeRunSync() === User(\"joe\", 27)\n      client.expect[User](DELETE(Uri.fromString(s\"http://localhost:$port/?reasons=because\").right.get)).unsafeRunSync() === User(\"because\", 27)\n    }\n\n    \"status codes\" >> {\n      client.fetch[Int](GET(Uri.fromString(s\"http://localhost:$port/status/200\").right.get))(resp => IO.pure(resp.status.code)).unsafeRunSync === 200\n      client.fetch[Int](GET(Uri.fromString(s\"http://localhost:$port/status/400\").right.get))(resp => IO.pure(resp.status.code)).unsafeRunSync === 400\n      client.fetch[Int](GET(Uri.fromString(s\"http://localhost:$port/status/500\").right.get))(resp => IO.pure(resp.status.code)).unsafeRunSync === 500\n    }\n  }\n\n  val path: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"path\", 27)))\n  val segment: String => F[Result[User]] = name => Applicative[F].pure(successWith(Ok)(User(name, 27)))\n  val query: Int => F[Result[User]] = age => Applicative[F].pure(successWith(Ok)(User(\"query\", age)))\n  val header: Int => F[Result[User]] = age => Applicative[F].pure(successWith(Ok)(User(\"header\", age)))\n  val fixed: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"fixed\", 27)))\n  val input: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"input\", 27)))\n  val clientHdr: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"client header\", 27)))\n  val coll: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"coll\", 27)))\n  val matching: Map[String, String] => F[Result[User]] = matches => Applicative[F].pure(successWith(Ok)(User(matches.mkString(\",\"), 27)))\n  val send: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"send\", 27)))\n  val get: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"get\", 27)))\n  val put: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"put\", 27)))\n  val putB: User => F[Result[User]] = user => Applicative[F].pure(successWith(Ok)(user))\n  val post: () => F[Result[User]] = () => Applicative[F].pure(successWith(Ok)(User(\"post\", 27)))\n  val postB: User => F[Result[User]] = user => Applicative[F].pure(successWith(Ok)(user))\n  val delete: List[String] => F[Result[User]] = reasons => {\n    Applicative[F].pure(successWith(Ok)(User(reasons.mkString(\",\"), 27)))\n  }\n  val code200: () => F[Result[String]] = () => Applicative[F].pure(successWith(Ok)(\"\"))\n  val code400: () => F[Result[String]] = () => Applicative[F].pure(errorWith(BadRequest, \"meh\"))\n  val code500: () => F[Result[String]] = () => Applicative[F].pure(errorWith(InternalServerError, \"boom\"))\n}\n"
  },
  {
    "path": "http4s-client/src/main/scala/typedapi/client/http4s/package.scala",
    "content": "package typedapi.client\n\nimport cats.{Monad, MonadError, Applicative}\nimport org.http4s._\nimport org.http4s.client._\nimport org.http4s.Status.Successful\n\nimport scala.language.higherKinds\n\npackage object http4s {\n\n  private implicit class Http4sRequestOps[F[_]](req: Request[F]) {\n\n    def withQuery(queries: Map[String, List[String]]): Request[F] = {\n      if (queries.nonEmpty) {\n        val q   = org.http4s.Query.fromMap(queries)\n        val uri = Uri(req.uri.scheme, req.uri.authority, req.uri.path, q, req.uri.fragment)\n\n        req.withUri(uri)\n      }\n      else req\n    }\n\n    def withHeaders(headers: Map[String, String]): Request[F] = {\n      if (headers.nonEmpty) {\n        val h: List[Header] = headers.map { case (k, v) => org.http4s.Header(k, v) }(collection.breakOut)\n\n        req.withHeaders(Headers(h))\n      }\n      else req\n    }\n\n    def run(cm: ClientManager[Client[F]])(implicit F: Applicative[F]): F[Response[F]] =\n      cm.client.fetch(req)(resp => F.pure(resp))\n  }\n\n  private implicit class Http4sResponseOps[F[_]](resp: Response[F]) {\n\n    def decode[A](implicit d: EntityDecoder[F, A], F: MonadError[F, Throwable]): F[A] = resp match {\n      case Successful(_resp) =>\n        d.decode(_resp, strict = false).fold(throw _, identity)\n      case failedResponse =>\n        F.raiseError(UnexpectedStatus(failedResponse.status))\n    }\n  }\n\n  implicit def rawGetRequest[F[_]](implicit F: Applicative[F]) = new RawGetRequest[Client[F], F] {\n    type Resp = Response[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[Resp] = {\n      val request = Request[F](Method.GET, Uri.unsafeFromString(deriveUriString(cm, uri)))\n        .withQuery(queries)\n        .withHeaders(headers)\n\n      request.run(cm)\n    }\n  }\n\n  implicit def getRequest[F[_], A](implicit decoder: EntityDecoder[F, A], F: MonadError[F, Throwable]) = new GetRequest[Client[F], F, A] {\n    private val raw = rawGetRequest[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[A] =\n      F.flatMap(raw(uri, queries, headers, cm))(_.decode[A])\n  }\n\n  implicit def rawPutRequest[F[_]](implicit F: Applicative[F]) = new RawPutRequest[Client[F], F] {\n    type Resp = Response[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[Resp] = {\n      val request = Request[F](Method.PUT, Uri.unsafeFromString(deriveUriString(cm, uri)))\n        .withQuery(queries)\n        .withHeaders(headers)\n\n      request.run(cm)\n    }\n  }\n\n  implicit def putRequest[F[_], A](implicit decoder: EntityDecoder[F, A], F: MonadError[F, Throwable]) = new PutRequest[Client[F], F, A] {\n    private val raw = rawPutRequest[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[A] =\n      F.flatMap(raw(uri, queries, headers, cm))(_.decode[A])\n  }\n\n  implicit def rawPutBodyRequest[F[_], Bd](implicit encoder: EntityEncoder[F, Bd], F: Monad[F]) = new RawPutWithBodyRequest[Client[F], F, Bd] {\n    type Resp = Response[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Client[F]]): F[Resp] = {\n      val requestF = Request[F](Method.PUT, Uri.unsafeFromString(deriveUriString(cm, uri)))\n        .withQuery(queries)\n        .withHeaders(headers)\n        .withBody(body)\n\n      F.flatMap(requestF)(_.run(cm))\n    }\n  }\n\n  implicit def putBodyRequest[F[_], Bd, A](implicit encoder: EntityEncoder[F, Bd], \n                                                    decoder: EntityDecoder[F, A], \n                                                    F: MonadError[F, Throwable]) = new PutWithBodyRequest[Client[F], F, Bd, A] {\n    private val raw = rawPutBodyRequest[F, Bd]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Client[F]]): F[A] =\n      F.flatMap(raw(uri, queries, headers, body, cm))(_.decode[A])\n  }\n\n  implicit def rawPostRequest[F[_]](implicit F: Applicative[F]) = new RawPostRequest[Client[F], F] {\n    type Resp = Response[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[Resp] = {\n      val request = Request[F](Method.POST, Uri.unsafeFromString(deriveUriString(cm, uri)))\n        .withQuery(queries)\n        .withHeaders(headers)\n\n      request.run(cm)\n    }\n  }\n\n  implicit def postRequest[F[_], A](implicit decoder: EntityDecoder[F, A], F: MonadError[F, Throwable]) = new PostRequest[Client[F], F, A] {\n    private val raw = rawPostRequest[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[A] =\n      F.flatMap(raw(uri, queries, headers, cm))(_.decode[A])\n  }\n\n  implicit def rawPostBodyRequest[F[_], Bd](implicit encoder: EntityEncoder[F, Bd], \n                                                     F: Monad[F]) = new RawPostWithBodyRequest[Client[F], F, Bd] {\n    type Resp = Response[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Client[F]]): F[Resp] = {\n      val requestF = Request[F](Method.POST, Uri.unsafeFromString(deriveUriString(cm, uri)))\n        .withQuery(queries)\n        .withHeaders(headers)\n        .withBody(body)\n\n      F.flatMap(requestF)(_.run(cm))\n    }\n  }\n\n  implicit def postBodyRequest[F[_], Bd, A](implicit encoder: EntityEncoder[F, Bd], \n                                                     decoder: EntityDecoder[F, A], \n                                                     F: MonadError[F, Throwable]) = new PostWithBodyRequest[Client[F], F, Bd, A] {\n    private val raw = rawPostBodyRequest[F, Bd]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Client[F]]): F[A] =\n      F.flatMap(raw(uri, queries, headers, body, cm))(_.decode[A])\n  }\n\n  implicit def rawDeleteRequest[F[_]](implicit F: Applicative[F]) = new RawDeleteRequest[Client[F], F] {\n    type Resp = Response[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[Resp] = {\n      val request = Request[F](Method.DELETE, Uri.unsafeFromString(deriveUriString(cm, uri)))\n        .withQuery(queries)\n        .withHeaders(headers)\n\n      request.run(cm)\n    }\n  }\n\n  implicit def deleteRequest[F[_], A](implicit decoder: EntityDecoder[F, A], F: MonadError[F, Throwable]) = new DeleteRequest[Client[F], F, A] {\n    private val raw = rawDeleteRequest[F]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Client[F]]): F[A] =\n      F.flatMap(raw(uri, queries, headers, cm))(_.decode[A])\n  }\n}\n"
  },
  {
    "path": "http4s-server/src/main/scala/typedapi/server/htt4ps/package.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared.MethodType\nimport cats.Monad\nimport cats.implicits._\nimport cats.effect.IO\nimport org.http4s._\nimport org.http4s.dsl._\nimport org.http4s.dsl.impl.EntityResponseGenerator\nimport org.http4s.server.Server\nimport org.http4s.server.blaze.BlazeBuilder\nimport shapeless._\nimport shapeless.ops.hlist.Prepend\n\nimport scala.language.higherKinds\n\npackage object http4s {\n\n  private def getHeaders(raw: Map[String, String]): List[Header.Raw] = \n    raw.map { case (key, value) => Header(key, value) }(collection.breakOut)\n\n  implicit def noReqBodyExecutor[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, F[_]: Monad, FOut](implicit encoder: EntityEncoder[F, FOut]) = \n    new NoReqBodyExecutor[El, KIn, VIn, M, F, FOut] {\n      type R   = Request[F]\n      type Out = F[Response[F]]\n\n      private val dsl = Http4sDsl[F]\n      import dsl._\n\n      private def respGenerator(code: Status) = new EntityResponseGenerator[F] { val status = code }\n\n      def apply(req: R, eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, VIn, F, FOut]): Either[ExtractionError, Out] = {\n        extract(eReq, endpoint).map { extracted =>\n          Monad[F].flatMap(execute(extracted, endpoint)) {\n            case Right((code, response)) =>\n              respGenerator(Status(code.statusCode))(response, getHeaders(endpoint.headers): _*)\n\n            case Left(HttpError(code, msg)) =>\n              respGenerator(Status(code.statusCode))(msg, getHeaders(endpoint.headers): _*)\n          }\n        }\n      }\n    }\n\n  implicit def withReqBodyExecutor[El <: HList, KIn <: HList, VIn <: HList, Bd, M <: MethodType, ROut <: HList, POut <: HList, F[_]: Monad, FOut]\n    (implicit encoder: EntityEncoder[F, FOut], \n              decoder: EntityDecoder[F, Bd],\n              _prepend: Prepend.Aux[ROut, Bd :: HNil, POut], \n              _eqProof: POut =:= VIn) = new ReqBodyExecutor[El, KIn, VIn, Bd, M, ROut, POut, F, FOut] {\n    type R   = Request[F]\n    type Out = F[Response[F]]\n\n    implicit val prepend = _prepend\n    implicit val eqProof = _eqProof\n\n    private val dsl = Http4sDsl[F]\n    import dsl._\n\n    private def respGenerator(code: Status) = new EntityResponseGenerator[F] { val status = code }\n\n    def apply(req: R, eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, (BodyType[Bd], ROut), F, FOut]): Either[ExtractionError, Out] = {\n      extract(eReq, endpoint).map { case (_, extracted) =>\n        for {\n          body     <- req.as[Bd]\n          response <- execute(extracted, body, endpoint).flatMap {\n            case Right((code, response)) =>\n              respGenerator(Status(code.statusCode))(response, getHeaders(endpoint.headers): _*)\n\n            case Left(HttpError(code, msg)) =>\n              respGenerator(Status(code.statusCode))(msg, getHeaders(endpoint.headers): _*)\n          }\n        } yield response\n      }\n    }\n  }\n\n  implicit val mountEndpoints = new MountEndpoints[BlazeBuilder[IO], Request[IO], IO[Response[IO]]] {\n\n    import io._\n\n    type Out = IO[Server[IO]]\n\n    def apply(server: ServerManager[BlazeBuilder[IO]], endpoints: List[Serve[Request[IO], IO[Response[IO]]]]): Out = {\n      val service = HttpService[IO] {\n        case request =>\n          def execute(eps: List[Serve[Request[IO], IO[Response[IO]]]], eReq: EndpointRequest): IO[Response[IO]] = eps match {\n            case collection.immutable.::(endpoint, tail) => endpoint(request, eReq) match {\n              case Right(response)            => response\n              case Left(RouteNotFound)        => execute(tail, eReq)\n              case Left(BadRouteRequest(msg)) => io.BadRequest(msg)\n            }\n\n            case Nil => io.NotFound(\"uri = \" + request.uri)\n          }\n\n          val eReq = EndpointRequest(\n            request.method.name, \n            {\n              val path = request.uri.path.split(\"/\")\n\n              if (path.isEmpty) List.empty\n              else              path.tail.toList\n            },\n            request.uri.multiParams.map { case (key, value) => key -> value.toList },\n            request.headers.toList.map(header => header.name.toString.toLowerCase -> header.value)(collection.breakOut)\n          )\n\n          if (request.method.name == \"OPTIONS\") {\n            IO(Response(headers = Headers(getHeaders(optionsHeaders(endpoints, eReq)))))\n          }\n          else\n            execute(endpoints, eReq)\n      }\n\n      server.server.bindHttp(server.port, server.host).mountService(service, \"/\").start\n    }\n  }\n}\n"
  },
  {
    "path": "js-client/src/main/scala/typedapi/client/js/package.scala",
    "content": "package typedapi.client\n\nimport typedapi.util._\nimport org.scalajs.dom.XMLHttpRequest\nimport org.scalajs.dom.ext.Ajax\n\nimport scala.concurrent.{Future, ExecutionContext}\n\npackage object js {\n\n  private def renderQueries(queries: Map[String, List[String]]): String = \n    if (queries.nonEmpty)\n      queries\n        .map { case (key, values) => s\"$key=${values.mkString(\",\")}\" }\n        .mkString(\"?\", \"&\", \"\")\n  else\n    \"\"\n\n  private def flatten[A](decoded: Future[Either[Exception, A]])(implicit ec: ExecutionContext): Future[A] = decoded.flatMap {\n    case Right(a)    => Future.successful(a)\n    case Left(error) => Future.failed(error)\n  }\n\n  implicit def rawGetRequest(implicit ec: ExecutionContext) = new RawGetRequest[Ajax.type, Future] {\n    type Resp = XMLHttpRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[Resp] =\n      cm.client\n        .get(\n          url     = deriveUriString(cm, uri) + renderQueries(queries),\n          headers = headers\n        )\n  }\n\n  implicit def getRequest[A](implicit decoder: Decoder[Future, A], ec: ExecutionContext) = new GetRequest[Ajax.type, Future, A] {\n    private val raw = rawGetRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap(response => flatten(decoder(response.responseText)))\n  }\n\n  implicit def rawPutRequest(implicit ec: ExecutionContext) = new RawPutRequest[Ajax.type, Future] {\n    type Resp = XMLHttpRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[Resp] =\n      cm.client\n        .put(\n          url     = deriveUriString(cm, uri) + renderQueries(queries),\n          headers = headers\n        )\n  }\n\n  implicit def putRequest[A](implicit decoder: Decoder[Future, A], ec: ExecutionContext) = new PutRequest[Ajax.type, Future, A] {\n    private val raw = rawPutRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap(response => flatten(decoder(response.responseText)))\n  }\n\n  implicit def rawPutBodyRequest[Bd](implicit encoder: Encoder[Future, Bd], ec: ExecutionContext) = new RawPutWithBodyRequest[Ajax.type, Future, Bd] {\n    type Resp = XMLHttpRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Ajax.type]): Future[Resp] =\n      encoder(body).flatMap { encoded => \n        cm.client\n          .put(\n            url     = deriveUriString(cm, uri) + renderQueries(queries),\n            headers = headers,\n            data    = encoded\n          )\n      }\n  }\n\n  implicit def putBodyRequest[Bd, A](implicit encoder: Encoder[Future, Bd], decoder: Decoder[Future, A], ec: ExecutionContext) = new PutWithBodyRequest[Ajax.type, Future, Bd, A] {\n    private val raw = rawPutBodyRequest[Bd]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Ajax.type]): Future[A] =\n      raw(uri, queries, headers, body, cm).flatMap(response => flatten(decoder(response.responseText)))\n  }\n\n  implicit def rawPostRequest(implicit ec: ExecutionContext) = new RawPostRequest[Ajax.type, Future] {\n    type Resp = XMLHttpRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[Resp] =\n      cm.client\n        .post(\n          url     = deriveUriString(cm, uri) + renderQueries(queries),\n          headers = headers\n        )\n  }\n\n  implicit def postRequest[A](implicit decoder: Decoder[Future, A], ec: ExecutionContext) = new PostRequest[Ajax.type, Future, A] {\n    private val raw = rawPostRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap(response => flatten(decoder(response.responseText)))\n  }\n\n  implicit def rawPostBodyRequest[Bd](implicit encoder: Encoder[Future, Bd], ec: ExecutionContext) = new RawPostWithBodyRequest[Ajax.type, Future, Bd] {\n    type Resp = XMLHttpRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Ajax.type]): Future[Resp] =\n      encoder(body).flatMap { encoded =>\n        cm.client\n          .post(\n            url     = deriveUriString(cm, uri) + renderQueries(queries),\n            headers = headers,\n            data    = encoded\n          )\n      }\n  }\n\n  implicit def postBodyRequest[Bd, A](implicit encoder: Encoder[Future, Bd], decoder: Decoder[Future, A], ec: ExecutionContext) = new PostWithBodyRequest[Ajax.type, Future, Bd, A] {\n    private val raw = rawPostBodyRequest[Bd]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Ajax.type]): Future[A] =\n      raw(uri, queries, headers, body, cm).flatMap(response => flatten(decoder(response.responseText)))\n  }\n\n  implicit def rawDeleteRequest(implicit ec: ExecutionContext) = new RawDeleteRequest[Ajax.type, Future] {\n    type Resp = XMLHttpRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[Resp] =\n      cm.client\n        .delete(\n          url     = deriveUriString(cm, uri) + renderQueries(queries),\n          headers = headers\n        )\n  }\n\n  implicit def deleteRequest[A](implicit decoder: Decoder[Future, A], ec: ExecutionContext) = new DeleteRequest[Ajax.type, Future, A] {\n    private val raw = rawDeleteRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Ajax.type]): Future[A] =\n      raw(uri, queries, headers, cm).flatMap(response => flatten(decoder(response.responseText)))\n  }\n}\n"
  },
  {
    "path": "project/build.properties",
    "content": "sbt.version=1.0.4"
  },
  {
    "path": "project/build.scala",
    "content": "import sbt._\n\nobject Dependencies {\n\n  private val specs2V = \"3.9.4\"\n\n  val shared = Seq(\n    \"com.chuusai\" %% \"shapeless\" % \"2.3.3\" % Compile,\n\n    \"org.specs2\"  %% \"specs2-core\" % specs2V % Test\n  )\n\n  val client = Seq(\n    \"org.specs2\"  %% \"specs2-core\" % specs2V % Test\n  )\n\n  val server = Seq(\n    \"org.specs2\"  %% \"specs2-core\" % specs2V % Test\n  )\n\n  private val http4sV = \"0.18.0\"\n\n  val http4sClient = Seq(\n    \"org.http4s\" %% \"http4s-blaze-client\" % http4sV % Provided,\n  )\n\n  val http4sServer = Seq(\n    \"org.http4s\" %% \"http4s-blaze-server\" % http4sV % Provided,\n    \"org.http4s\" %% \"http4s-dsl\" % http4sV % Provided\n  )\n\n  private val akkaHttpV = \"10.0.13\"\n\n  val akkaHttpClient = Seq(\n    \"com.typesafe.akka\" %% \"akka-http\" % akkaHttpV % Provided,\n    \"com.typesafe.akka\" %% \"akka-http-core\" % akkaHttpV % Provided\n  )\n\n  val akkaHttpServer = Seq(\n    \"com.typesafe.akka\" %% \"akka-http\" % akkaHttpV % Provided,\n    \"com.typesafe.akka\" %% \"akka-http-core\" % akkaHttpV % Provided\n  )\n\n  private val scalajHttpV = \"2.4.1\"\n\n  val scalajHttpClient = Seq(\n    \"org.scalaj\" %% \"scalaj-http\" % scalajHttpV % Provided\n  )\n\n  private val circeV = \"0.9.1\"\n\n  val httpSupportTests = Seq(\n    \"org.specs2\" %% \"specs2-core\" % specs2V % Test,\n\n    \"org.http4s\" %% \"http4s-blaze-client\" % http4sV % Test,\n    \"org.http4s\" %% \"http4s-blaze-server\" % http4sV % Test,\n    \"org.http4s\" %% \"http4s-dsl\" % http4sV          % Test,\n    \"org.http4s\" %% \"http4s-circe\" % http4sV        % Test,\n    \"com.typesafe.akka\" %% \"akka-http\" % akkaHttpV  % Test,\n    \"org.scalaj\" %% \"scalaj-http\" % scalajHttpV     % Test,\n\n    \"io.circe\"   %% \"circe-core\" % circeV               % Test,\n    \"io.circe\"   %% \"circe-parser\" % circeV             % Test,\n    \"io.circe\"   %% \"circe-generic\" % circeV            % Test,\n    \"de.heikoseeberger\" %% \"akka-http-circe\" % \"1.21.0\" % Test,\n\n    \"org.specs2\" %% \"specs2-core\" % specs2V         % Test\n  )\n\n  val ammoniteSupport = Seq(\n    \"org.scalaj\" %% \"scalaj-http\" % scalajHttpV % Compile\n  )\n}\n"
  },
  {
    "path": "project/plugins.sbt",
    "content": "addSbtPlugin(\"org.xerial.sbt\" % \"sbt-sonatype\" % \"2.3\")\n\naddSbtPlugin(\"com.jsuereth\" % \"sbt-pgp\" % \"1.1.0\")\n\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % \"0.6.22\")\n"
  },
  {
    "path": "scalaj-http-client/src/main/scala/typedapi/client/scalajhttp/package.scala",
    "content": "package typedapi.client\n\nimport typedapi.util._\nimport scalaj.http._\n\npackage object scalajhttp {\n\n  type Id[A]       = A\n  type Blocking[A] = Either[Exception, A]\n\n  private def reduceQueries(queries: Map[String, List[String]]): Map[String, String] = \n    queries.map { case (key, values) => key -> values.mkString(\",\") }(collection.breakOut)\n\n  implicit def rawGetRequest = new RawGetRequest[Http.type, Id] {\n    type Resp = HttpResponse[String]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Id[Resp] = {\n      val req = cm.client(deriveUriString(cm, uri)).params(reduceQueries(queries)).headers(headers).method(\"GET\")\n\n      req.asString\n    }\n  }\n\n  implicit def getRequest[A](implicit decoder: Decoder[Id, A]) = new GetRequest[Http.type, Blocking, A] {\n    private val raw = rawGetRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Blocking[A] =\n      decoder(raw(uri, queries, headers, cm).body)\n  }\n\n  implicit def rawPutRequest = new RawPutRequest[Http.type, Id] {\n    type Resp = HttpResponse[String]\n    \n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Id[Resp] = {\n      val req = cm.client(deriveUriString(cm, uri)).params(reduceQueries(queries)).headers(headers).method(\"PUT\")\n\n      req.asString\n    }\n  }\n\n  implicit def putRequest[A](implicit decoder: Decoder[Id, A]) = new PutRequest[Http.type, Blocking, A] {\n    private val raw = rawPutRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Blocking[A] =\n      decoder(raw(uri, queries, headers, cm).body)\n  }\n\n  implicit def rawPutBodyRequest[Bd](implicit encoder: Encoder[Id, Bd]) = new RawPutWithBodyRequest[Http.type, Id, Bd] {\n    type Resp = HttpResponse[String]\n    \n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Http.type]): Id[Resp] = {\n      val req = cm.client(deriveUriString(cm, uri)).params(reduceQueries(queries)).headers(headers).put(encoder(body))\n\n      req.asString\n    }\n  }\n\n  implicit def putBodyRequest[Bd, A](implicit encoder: Encoder[Id, Bd], decoder: Decoder[Id, A]) = new PutWithBodyRequest[Http.type, Blocking, Bd, A] {\n    private val raw = rawPutBodyRequest[Bd]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Http.type]): Blocking[A] =\n      decoder(raw(uri, queries, headers, body, cm).body)\n  }\n\n  implicit def rawPostRequest = new RawPostRequest[Http.type, Id] {\n    type Resp = HttpResponse[String]\n    \n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Id[Resp] = {\n      val req = cm.client(deriveUriString(cm, uri)).params(reduceQueries(queries)).headers(headers).method(\"POST\")\n\n      req.asString\n    }\n  }\n\n  implicit def postRequest[A](implicit decoder: Decoder[Id, A]) = new PostRequest[Http.type, Blocking, A] {\n    private val raw = rawPostRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Blocking[A] =\n      decoder(raw(uri, queries, headers, cm).body)\n  }\n\n  implicit def rawPostBodyRequest[Bd](implicit encoder: Encoder[Id, Bd]) = new RawPostWithBodyRequest[Http.type, Id, Bd] {\n    type Resp = HttpResponse[String]\n    \n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Http.type]): Id[Resp] = {\n      val req = cm.client(deriveUriString(cm, uri)).params(reduceQueries(queries)).headers(headers).postData(encoder(body))\n\n      req.asString\n    }\n  }\n\n  implicit def postBodyRequest[Bd, A](implicit encoder: Encoder[Id, Bd], decoder: Decoder[Id, A]) = new PostWithBodyRequest[Http.type, Blocking, Bd, A] {\n    private val raw = rawPostBodyRequest[Bd]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd, cm: ClientManager[Http.type]): Blocking[A] =\n      decoder(raw(uri, queries, headers, body, cm).body)\n  }\n\n  implicit def rawDeleteRequest = new RawDeleteRequest[Http.type, Id] {\n    type Resp = HttpResponse[String]\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Id[Resp] = {\n      val req = cm.client(deriveUriString(cm, uri)).params(reduceQueries(queries)).headers(headers).method(\"DELETE\")\n\n      req.asString\n    }\n  }\n\n  implicit def deleteRequest[A](implicit decoder: Decoder[Id, A]) = new DeleteRequest[Http.type, Blocking, A] {\n    private val raw = rawDeleteRequest\n\n    def apply(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], cm: ClientManager[Http.type]): Blocking[A] =\n      decoder(raw(uri, queries, headers, cm).body)\n  }\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/Endpoint.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared._\nimport shapeless._\nimport shapeless.labelled.FieldType\nimport shapeless.ops.function._\n\nimport scala.language.higherKinds\n\n/** Represents a server endpoint and is basically a function which gets the expected input `VIn` and returns the expected output. */\nabstract class Endpoint[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, F[_], Out]\n    (val method: String, val extractor: RouteExtractor.Aux[El, KIn, VIn, M, HNil, ROut], val headers: Map[String, String]) {\n\n  def apply(in: VIn): F[Result[Out]]\n}\n\n/** Request representation which every server implementation has to provide. */\nfinal case class EndpointRequest(method: String, \n                                 uri: List[String],\n                                 queries: Map[String, List[String]],\n                                 headers: Map[String, String])\n\nfinal class ExecutableDerivation[F[_]] {\n\n  final class Derivation[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, Fn, Out]\n    (extractor: RouteExtractor.Aux[El, KIn, VIn, M, HNil, ROut],\n     method: String,\n     headers: Map[String, String],\n     fnToVIn: FnToProduct.Aux[Fn, VIn => F[Result[Out]]]) {\n\n    /** Restricts type of parameter `fn` to a function defined by the given API:\n      * \n      * {{{\n      * val Api = := :> Segment[String]('name) :> Get[User]\n      * \n      * derive[IO](Api).from(name: String => IO.pure(User(name)))\n      * }}}\n      */\n    def from(fn: Fn): Endpoint[El, KIn, VIn, M, ROut, F, Out] =\n      new Endpoint[El, KIn, VIn, M, ROut, F, Out](method, extractor, headers) {\n        private val fin = fnToVIn(fn)\n\n        def apply(in: VIn): F[Result[Out]] = fin(in)\n      }\n  }\n\n  def apply[H <: HList, FH <: HList, El <: HList, KIn <: HList, VIn <: HList, ROut, Fn, M <: MethodType, MT <: MediaType, Out]\n    (apiList: ApiTypeCarrier[H])\n    (implicit filter: FilterClientElements.Aux[H, FH],\n              folder: Lazy[TypeLevelFoldLeft.Aux[FH, Unit, (El, KIn, VIn, M, FieldType[MT, Out])]],\n              extractor: RouteExtractor.Aux[El, KIn, VIn, M, HNil, ROut],\n              methodShow: MethodToString[M],\n              serverHeaders: ServerHeaderExtractor[El],\n              inToFn: Lazy[FnFromProduct.Aux[VIn => F[Result[Out]], Fn]],\n              fnToVIn: Lazy[FnToProduct.Aux[Fn, VIn => F[Result[Out]]]]): Derivation[El, KIn, VIn, M, ROut, Fn, Out] =\n    new Derivation[El, KIn, VIn, M, ROut, Fn, Out](extractor, methodShow.show, serverHeaders(Map.empty), fnToVIn.value)\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/EndpointComposition.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared._\nimport shapeless._\nimport shapeless.labelled.FieldType\nimport shapeless.ops.function._\n\nimport scala.language.higherKinds\nimport scala.annotation.implicitNotFound\n\n/** Fuses [[RouteExtractor]] and the endpoint function into an [[Endpoint]]. */\ntrait EndpointConstructor[F[_], Fn, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, Out] {\n\n  def apply(fn: Fn): Endpoint[El, KIn, VIn, M, ROut, F, Out]\n}\n\n/** Compiles RouteExtractor and FunApply for every API endpoint and generates expected list of endpoint functions. */\n@implicitNotFound(\"\"\"Could not precompile your API. This can happen when you try to extract an value from the route which is not supported (ValueExtractor in RouteExtractor.scala)\n \ntransformed: ${H}\"\"\")\nsealed trait PrecompileEndpoint[F[_], H <: HList] {\n\n  // list of expected endpoint functions\n  type Fns <: HList\n  // list of endpoint constructors\n  type Consts <: HList\n\n  def constructors: Consts\n}\n\nobject PrecompileEndpoint extends PrecompileEndpointLowPrio {\n\n  type Aux[F[_], H <: HList, Fns0 <: HList, Consts0 <: HList] = PrecompileEndpoint[F, H] {\n    type Fns    = Fns0\n    type Consts = Consts0\n  }\n}\n\ntrait PrecompileEndpointLowPrio {\n\n  implicit def hnilPrecompiledCase[F[_]] = new PrecompileEndpoint[F, HNil] {\n    type Fns    = HNil\n    type Consts = HNil\n\n    val constructors = HNil\n  }\n\n  implicit def constructorsCase[F[_], Fn, El <: HList, KIn <: HList, VIn <: HList, MT <: MediaType, Out, M <: MethodType, ROut, T <: HList]\n    (implicit extractor: RouteExtractor.Aux[El, KIn, VIn, M, HNil, ROut],\n              methodShow: MethodToString[M],\n              serverHeaders: ServerHeaderExtractor[El],\n              vinToFn: FnFromProduct.Aux[VIn => F[Result[Out]], Fn],\n              fnToVIn: Lazy[FnToProduct.Aux[Fn, VIn => F[Result[Out]]]],\n              next: PrecompileEndpoint[F, T]) =\n    new PrecompileEndpoint[F, (El, KIn, VIn, M, FieldType[MT, Out]) :: T] {\n      type Fns    = Fn :: next.Fns\n      type Consts = EndpointConstructor[F, Fn, El, KIn, VIn, M, ROut, Out] :: next.Consts\n\n      val constructor = new EndpointConstructor[F, Fn, El, KIn, VIn, M, ROut, Out] {\n        def apply(fn: Fn): Endpoint[El, KIn, VIn, M, ROut, F, Out] = new Endpoint[El, KIn, VIn, M, ROut, F, Out](methodShow.show, extractor, serverHeaders(Map.empty)) {\n          private val fin = fnToVIn.value(fn)\n\n          def apply(in: VIn): F[Result[Out]] = fin(in)\n        }\n      }\n\n      val constructors = constructor :: next.constructors\n    }\n}\n\n@implicitNotFound(\"\"\"Whoops, you should not be here. This seems to be a bug.\n\nconstructors: ${Consts}\nfunctions: ${Fns}\"\"\")\nsealed trait MergeToEndpoint[F[_], Consts <: HList, Fns <: HList] {\n\n  type Out <: HList\n\n  def apply(constructors: Consts, fns: Fns): Out\n}\n\nobject MergeToEndpoint extends MergeToEndpointLowPrio {\n\n  type Aux[F[_], Consts <: HList, Fns <: HList, Out0 <: HList] = MergeToEndpoint[F, Consts, Fns] { type Out = Out0 }\n}\n\ntrait MergeToEndpointLowPrio {\n\n  implicit def hnilMergeCase[F[_]] = new MergeToEndpoint[F, HNil, HNil] {\n    type Out = HNil\n\n    def apply(constructors: HNil, fns: HNil): Out = HNil\n  }\n\n  implicit def mergeCase[F[_], El <: HList, KIn <: HList, VIn <: HList, Out0, M <: MethodType, ROut, Consts <: HList, Fn, Fns <: HList]\n    (implicit next: MergeToEndpoint[F, Consts, Fns]) =\n    new MergeToEndpoint[F, EndpointConstructor[F, Fn, El, KIn, VIn, M, ROut, Out0] :: Consts, Fn :: Fns] {\n      type Out = Endpoint[El, KIn, VIn, M, ROut, F, Out0] :: next.Out\n\n      def apply(constructors: EndpointConstructor[F, Fn, El, KIn, VIn, M, ROut, Out0] :: Consts, fns: Fn :: Fns): Out = {\n        val endpoint = constructors.head(fns.head)\n\n        endpoint :: next(constructors.tail, fns.tail)\n      }\n    }\n}\n\nfinal class ExecutableCompositionDerivation[F[_]] {\n\n  final class Derivation[H <: HList, Fns <: HList, Consts <: HList, Out <: HList, Drv](pre: PrecompileEndpoint.Aux[F, H, Fns, Consts], \n                                                                                       merge: MergeToEndpoint.Aux[F, Consts, Fns, Out],\n                                                                                       derived: FnFromProduct.Aux[Fns => Out, Drv]) {\n\n    /** Restricts type of input parameter to a composition of functions defined by the precompile-stage.\n      *\n      * {{{\n      * val Api =\n      *   (:= :> Segment[String]('name) :> Get[User]) :|:\n      *   (:= :> \"foo\" :> Segment[String]('name) :> Get[User])\n      * \n      * val f0: String => IO[User] = name => IO.pure(User(name))\n      * val f1: String => IO[User] = name => IO.pure(User(name))\n      * deriveAll[IO](Api).from(f0 _, f1 _)\n      * }}}\n      */\n    val from: Drv = derived.apply(fns => merge(pre.constructors, fns))\n  }\n\n  def apply[H <: HList, FH <: HList, Fold <: HList, Fns <: HList, FnsTup, Consts <: HList, Out <: HList, Drv](apiLists: CompositionCons[H])\n                                      (implicit filter: FilterClientElementsList.Aux[H, FH],\n                                                folder: TypeLevelFoldLeftList.Aux[FH, Fold],\n                                                pre: PrecompileEndpoint.Aux[F, Fold, Fns, Consts],\n                                                merge: MergeToEndpoint.Aux[F, Consts, Fns, Out],\n                                                derived: FnFromProduct.Aux[Fns => Out, Drv]): Derivation[Fold, Fns, Consts, Out, Drv] =\n    new Derivation[Fold, Fns, Consts, Out, Drv](pre, merge, derived)\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/EndpointExecutor.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared.MethodType\nimport shapeless._\nimport shapeless.ops.hlist.Prepend\n\nimport scala.language.higherKinds\nimport scala.annotation.implicitNotFound\n\n@implicitNotFound(\"\"\"Cannot find EndpointExecutor. Do you miss some implicit values e.g. encoder/decoder?\n\nelements: ${El}\ninput keys: ${KIn}\ninput values: ${VIn}\"\"\")\nsealed trait EndpointExecutor[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, F[_], FOut] {\n\n  type R\n  type Out\n\n  def extract(eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, ROut, F, FOut]): Either[ExtractionError, ROut] = \n    endpoint.extractor(eReq, HNil)\n\n  def apply(req: R, eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, ROut, F, FOut]): Either[ExtractionError, Out]\n}\n\nobject EndpointExecutor {\n\n  type Aux[R0, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, F[_], FOut, Out0] = EndpointExecutor[El, KIn, VIn, M, ROut, F, FOut] {\n    type R   = R0\n    type Out = Out0\n  }\n}\n\ntrait NoReqBodyExecutor[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, F[_], FOut] extends EndpointExecutor[El, KIn, VIn, M, VIn, F, FOut] {\n\n  protected def execute(input: VIn, endpoint: Endpoint[El, KIn, VIn, M, VIn, F, FOut]): F[Result[FOut]] = \n    endpoint.apply(input)\n}\n\ntrait ReqBodyExecutor[El <: HList, KIn <: HList, VIn <: HList, Bd, M <: MethodType, ROut <: HList, POut <: HList, F[_], FOut] extends EndpointExecutor[El, KIn, VIn, M, (BodyType[Bd], ROut), F, FOut] {\n\n  implicit def prepend: Prepend.Aux[ROut, Bd :: HNil, POut]\n  implicit def eqProof: POut =:= VIn\n\n  protected def execute(input: ROut, body: Bd, endpoint: Endpoint[El, KIn, VIn, M, (BodyType[Bd], ROut), F, FOut]): F[Result[FOut]] = \n    endpoint.apply(input :+ body)\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/FilterClientElements.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared.{ClientHeaderElement, ClientHeaderParam, ClientHeaderCollParam}\nimport shapeless._\n\nsealed trait FilterClientElements[H <: HList] {\n\n  type Out <: HList\n}\n\nsealed trait FilterClientElementsLowPrio {\n\n  implicit val filterClientResult = new FilterClientElements[HNil] {\n    type Out = HNil\n  }\n\n  implicit def filterClientKeep[El, T <: HList](implicit next: FilterClientElements[T]) = new FilterClientElements[El :: T] {\n    type Out = El :: next.Out\n  }\n}\n\nobject FilterClientElements extends FilterClientElementsLowPrio {\n\n  type Aux[H <: HList, Out0 <: HList] = FilterClientElements[H] { type Out = Out0 }\n\n  implicit def filterClientEl[K, V, T <: HList](implicit next: FilterClientElements[T]) = new FilterClientElements[ClientHeaderElement[K, V] :: T] {\n    type Out = next.Out\n  }\n\n  implicit def filterClientParam[K, V, T <: HList](implicit next: FilterClientElements[T]) = new FilterClientElements[ClientHeaderParam[K, V] :: T] {\n    type Out = next.Out\n  }\n\n  implicit def filterClientCollParam[V, T <: HList](implicit next: FilterClientElements[T]) = new FilterClientElements[ClientHeaderCollParam[V] :: T] {\n    type Out = next.Out\n  }\n}\n\nsealed trait FilterClientElementsList[H <: HList] {\n\n  type Out <: HList\n}\n\nobject FilterClientElementsList {\n\n  type Aux[H <: HList, Out0 <: HList] = FilterClientElementsList[H] { type Out = Out0 }\n\n  implicit val filterClientListResult = new FilterClientElementsList[HNil] {\n    type Out = HNil\n  }\n\n  implicit def filterClientListStep[Api <: HList, T <: HList](implicit filtered: FilterClientElements[Api], next: FilterClientElementsList[T]) = \n    new FilterClientElementsList[Api :: T] {\n      type Out = filtered.Out :: next.Out\n    }\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/RouteExtractor.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared._\nimport shapeless.{HList, HNil, Witness}\nimport shapeless.labelled.FieldType\nimport shapeless.ops.hlist.Reverse\n\nimport scala.util.Try\nimport scala.annotation.implicitNotFound\n\nsealed trait ExtractionError\ncase object RouteNotFound extends ExtractionError\nfinal case class BadRouteRequest(msg: String) extends ExtractionError\n\n/** Builds a function which extracts inputs from a given requests based on the API. \n  *  - if a request path does not fit the API definition `RouteNotFound` is returned\n  *  - if a query, header, body, etc is missing `BadRouteRequest` is returned\n  */\n@implicitNotFound(\"\"\"Cannot find RouteExtractor. Maybe a ValueExtractor could not be found.\n\nelements: ${El}\ninput keys: ${KIn}\ninout values: ${VIn}\nmethod: ${M}\"\"\")\ntrait RouteExtractor[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList] {\n\n  type Out\n\n  def apply(request: EndpointRequest, inAgg: EIn): Either[ExtractionError, Out]\n}\n\nobject RouteExtractor extends RouteExtractorMediumPrio {\n\n  type Aux[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList, Out0] = RouteExtractor[El, KIn, VIn, M, EIn] { type Out = Out0 }\n\n  type Extract[Out] = Either[ExtractionError, Out]\n\n  def NotFoundE[Out]: Extract[Out] = Left(RouteNotFound)\n  def BadRequestE[Out](msg: String): Extract[Out] = Left(BadRouteRequest(msg))\n}\n\ntrait RouteExtractorLowPrio {\n\n  import RouteExtractor._\n\n  implicit def pathExtractor[S, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit wit: Witness.Aux[S], show: WitnessToString[S], next: RouteExtractor[El, KIn, VIn, M, EIn]) =\n    new RouteExtractor[shapeless.::[S, El], KIn, VIn, M, EIn] {\n    type Out = next.Out\n\n    def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = request.uri match {\n      case p :: tail => \n        if (p == show.show(wit.value))\n          next(request.copy(uri = tail), inAgg)\n        else\n          NotFoundE\n\n      case Nil => NotFoundE\n    }\n  }\n}\n\ntrait RouteExtractorMediumPrio extends RouteExtractorLowPrio {\n\n  import RouteExtractor._\n\n  private def checkEmptyPath[Out](request: EndpointRequest)(f: EndpointRequest => Extract[Out]): Extract[Out] = \n    if (request.uri.isEmpty)\n      f(request)\n    else\n      NotFoundE\n\n  implicit def segmentExtractor[El <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList](implicit value: ValueExtractor[V], next: RouteExtractor[El, KIn, VIn, M, shapeless.::[V, EIn]]) = \n    new RouteExtractor[shapeless.::[SegmentInput, El], shapeless.::[K, KIn], shapeless.::[V, VIn], M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = request.uri match {\n        case p :: tail => value(p).fold(NotFoundE[Out])(v => next(request.copy(uri = tail), v :: inAgg))\n        case Nil       => NotFoundE\n      }\n    }\n\n  implicit def queryExtractor[El <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], value: ValueExtractor[V], next: RouteExtractor[El, KIn, VIn, M, shapeless.::[V, EIn]]) =\n    new RouteExtractor[shapeless.::[QueryInput, El], shapeless.::[K, KIn], shapeless.::[V, VIn], M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        val key = show.show(wit.value)\n\n        req.queries.get(key).fold(BadRequestE[Out](s\"missing query '$key'\")) { raw =>\n          raw.headOption.flatMap(value.apply).fold(BadRequestE[Out](s\"query '$key' has not type ${value.typeDesc}\")) { v =>\n            next(request, v :: inAgg)\n          }\n        }\n      }\n    }\n\n  implicit def queryOptListExtractor[El <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], value: ValueExtractor[V], next: RouteExtractor[El, KIn, VIn, M, shapeless.::[Option[V], EIn]]) =\n    new RouteExtractor[shapeless.::[QueryInput, El], shapeless.::[K, KIn], shapeless.::[Option[V], VIn], M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        val key = show.show(wit.value)\n\n        req.queries.get(key).fold(next(request, None :: inAgg)) { raw =>\n          raw.headOption.flatMap(value.apply).fold(BadRequestE[Out](s\"query '$key' has not type ${value.typeDesc}\")) { v =>\n            next(request, Some(v) :: inAgg)\n          }\n        }\n      }\n    }\n\n  implicit def queryListExtractor[El <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], value: ValueExtractor[V], next: RouteExtractor[El, KIn, VIn, M, shapeless.::[List[V], EIn]]) =\n    new RouteExtractor[shapeless.::[QueryInput, El], shapeless.::[K, KIn], shapeless.::[List[V], VIn], M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        val key = show.show(wit.value)\n\n        req.queries.get(key).fold(next(request, Nil :: inAgg)) { raw =>\n          val vs = raw.flatMap(value.apply)\n\n          if (vs.length < raw.length)\n            BadRequestE(s\"some values of query '$key' are no ${value.typeDesc}\")\n          else\n            next(request, vs :: inAgg)\n        }\n      }\n    }\n\n  implicit def headerExtractor[El <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], value: ValueExtractor[V], next: RouteExtractor[El, KIn, VIn, M, shapeless.::[V, EIn]]) =\n    new RouteExtractor[shapeless.::[HeaderInput, El], shapeless.::[K, KIn], shapeless.::[V, VIn], M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        val key = show.show(wit.value).toLowerCase\n\n        req.headers.get(key).fold(BadRequestE[Out](s\"missing header '$key'\")) { raw =>\n          value(raw).fold(BadRequestE[Out](s\"header '$key' has not type ${value.typeDesc}\")) { v =>\n            next(request, v :: inAgg)\n          }\n        }\n      }\n    }\n\n  implicit def headerOptExtractor[El <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], value: ValueExtractor[V], next: RouteExtractor[El, KIn, VIn, M, shapeless.::[Option[V], EIn]]) =\n    new RouteExtractor[shapeless.::[HeaderInput, El], shapeless.::[K, KIn], shapeless.::[Option[V], VIn], M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        val key = show.show(wit.value)\n\n        req.headers.get(key.toLowerCase).fold(next(request, None :: inAgg)) { raw =>\n          value(raw).fold(BadRequestE[Out](s\"header '$key' has not type ${value.typeDesc}\")) { v =>\n            next(request, Some(v) :: inAgg)\n          }\n        }\n      }\n    }\n\n  implicit def fixedHeaderExtractor[K, V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit kWit: Witness.Aux[K], kShow: WitnessToString[K], vWit: Witness.Aux[V], vShow: WitnessToString[V], next: RouteExtractor[El, KIn, VIn, M, EIn]) =\n    new RouteExtractor[shapeless.::[FixedHeader[K, V], El], KIn, VIn, M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        val key   = kShow.show(kWit.value)\n        val value = vShow.show(vWit.value)\n\n        req.headers.get(key.toLowerCase).fold(BadRequestE[Out](s\"missing header '$key'\")) { raw =>\n          if (raw != value)\n            BadRequestE[Out](s\"header '$key' has unexpected value '${raw}' - expected '${value}'\")\n          else\n            next(request, inAgg)\n        }\n      }\n    }\n\n  implicit def ignoreServerHeaderSendExtractor[K, V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit next: RouteExtractor[El, KIn, VIn, M, EIn]) =\n    new RouteExtractor[shapeless.::[ServerHeaderSend[K, V], El], KIn, VIn, M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        next(request, inAgg)\n      }\n    }\n\n  implicit def serverHeaderMatchExtractor[El <: HList, K, V, KIn <: HList, VIn <: HList, M <: MethodType, EIn <: HList]\n      (implicit wit: Witness.Aux[K], show: WitnessToString[K], value: ValueExtractor[V], next: RouteExtractor[El, KIn, VIn, M, shapeless.::[Map[String, V], EIn]]) =\n    new RouteExtractor[shapeless.::[ServerHeaderMatchInput, El], shapeless.::[K, KIn], shapeless.::[Map[String, V], VIn], M, EIn] {\n      type Out = next.Out\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        val key      = show.show(wit.value).toLowerCase\n        val matchesE = req.headers.foldLeft[Either[ExtractionError, Map[String, V]]](Right(Map.empty)) { \n          case (Right(agg), (k, raw)) =>\n            if (k.contains(key)) {\n              value(raw).fold(BadRequestE[Map[String, V]](s\"header '$k' has not type ${value.typeDesc}\")) { v =>\n                Right(agg + (k -> v))\n              }\n            }\n            else\n              Right(agg)\n          case (error, _) => error\n        }\n\n        matchesE.fold(\n          error   => Left(error),\n          matches => next(request, matches :: inAgg)\n        )\n        \n      }\n    }\n\n  implicit def getExtractor[EIn <: HList, REIn <: HList](implicit rev: Reverse.Aux[EIn, REIn]) = new RouteExtractor[HNil, HNil, HNil, GetCall, EIn] {\n    type Out = REIn\n\n    def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n      if (req.method == \"GET\" || req.method == \"OPTIONS\") \n        Right(inAgg.reverse)\n      else \n        NotFoundE\n    }\n  }\n\n  implicit def putExtractor[EIn <: HList, REIn <: HList](implicit rev: Reverse.Aux[EIn, REIn]) = new RouteExtractor[HNil, HNil, HNil, PutCall, EIn] {\n    type Out = REIn\n\n    def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n      if (req.method == \"PUT\" || req.method == \"OPTIONS\") \n        Right(inAgg.reverse)\n      else \n        NotFoundE\n    }\n  }\n\n  implicit def putWithBodyExtractor[BMT <: MediaType, Bd, EIn <: HList] = \n    new RouteExtractor[HNil, shapeless.::[FieldType[BMT, BodyField.T], HNil], shapeless.::[Bd, HNil], PutWithBodyCall, EIn] {\n      type Out = (BodyType[Bd], EIn)\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        if (req.method == \"PUT\" || req.method == \"OPTIONS\")\n          Right((BodyType[Bd], inAgg))\n        else\n          NotFoundE\n      }\n    }\n\n  implicit def postExtractor[EIn <: HList] = new RouteExtractor[HNil, HNil, HNil, PostCall, EIn] {\n    type Out = EIn\n\n    def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n      if (req.method == \"POST\" || req.method == \"OPTIONS\") \n        Right(inAgg)\n      else \n        NotFoundE\n    }\n  }\n\n  implicit def postWithBodyExtractor[BMT <: MediaType, Bd, EIn <: HList, REIn <: HList] = \n    new RouteExtractor[HNil, shapeless.::[FieldType[BMT, BodyField.T], HNil], shapeless.::[Bd, HNil], PostWithBodyCall, EIn] {\n      type Out = (BodyType[Bd], EIn)\n\n      def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n        if (req.method == \"POST\" || req.method == \"OPTIONS\")\n          Right((BodyType[Bd], inAgg))\n        else\n          NotFoundE\n      }\n    }\n\n  implicit def deleteExtractor[EIn <: HList] = new RouteExtractor[HNil, HNil, HNil, DeleteCall, EIn] {\n    type Out = EIn\n\n    def apply(request: EndpointRequest, inAgg: EIn): Extract[Out] = checkEmptyPath(request) { req =>\n      if (req.method == \"DELETE\" || req.method == \"OPTIONS\")\n        Right(inAgg)\n      else \n        NotFoundE\n    }\n  }\n}\n\ntrait ValueExtractor[A] extends (String => Option[A]) {\n\n  def typeDesc: String\n}\n\nobject ValueExtractor extends ValueExtractorInstances\n\ntrait ValueExtractorInstances {\n\n  def extract[A](f: String => A, _typeDesc: String) = new ValueExtractor[A] {\n    val typeDesc = _typeDesc\n\n    def apply(raw: String): Option[A] = Try(f(raw)).toOption\n  }\n\n  implicit val booleanExtractor = extract[Boolean](_.toBoolean, \"Boolean\")\n  implicit val byteExtractor    = extract[Byte](_.toByte, \"Byte\")\n  implicit val shortExtractor   = extract[Short](_.toShort, \"Short\")\n  implicit val intExtractor     = extract[Int](_.toInt, \"Int\")\n  implicit val longExtractor    = extract[Long](_.toLong, \"Long\")\n  implicit val floatExtractor   = extract[Float](_.toFloat, \"Float\")\n  implicit val doubleExtractor  = extract[Double](_.toDouble, \"Double\")\n  implicit val stringExtractor  = extract[String](identity, \"String\")\n}\n\nfinal case class BodyType[Bd]()\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/Serve.scala",
    "content": "package typedapi.server\n\n/** Reduces an Endpoint and its EndpointExecutor to a simple Request => Response function. */\ntrait Serve[Req, Resp] {\n\n  def options(eReq: EndpointRequest): Option[(String, Map[String, String])]\n  def apply(req: Req, eReq: EndpointRequest): Either[ExtractionError, Resp]\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/ServeToList.scala",
    "content": "package typedapi.server\n\nimport shapeless._\n\nimport scala.annotation.implicitNotFound\n\n@implicitNotFound(\"\"\"Cannot find ServeToList instance to map Serve HList to List. Maybe you have different Request, Response types defined?. \n\nserves: ${H}\nrequest: ${Req}\nresponse: ${Resp}\"\"\")\nsealed trait ServeToList[H <: HList, Req, Resp] {\n\n  def apply(h: H): List[Serve[Req, Resp]]\n}\n\nobject ServeToList extends ServeToListLowPrio\n\ntrait ServeToListLowPrio {\n\n  implicit def hnilToList[Req, Resp] = new ServeToList[HNil, Req, Resp] {\n    def apply(h: HNil): List[Serve[Req, Resp]] = Nil\n  }\n\n  implicit def serveToList[Req, Resp, T <: HList](implicit next: ServeToList[T, Req, Resp]) = new ServeToList[Serve[Req, Resp] :: T, Req, Resp] {\n    def apply(h: Serve[Req, Resp] :: T): List[Serve[Req, Resp]] = h.head :: next(h.tail)\n  }\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/ServerHeaderExtractor.scala",
    "content": "package typedapi.server\n\nimport typedapi.shared._\nimport shapeless._\n\nimport scala.annotation.implicitNotFound\n\n@implicitNotFound(\"\"\"Whoops, you should not be here. This seems to be a bug.\n\nelements: ${El}\"\"\")\nsealed trait ServerHeaderExtractor[El <: HList] {\n\n  def apply(agg: Map[String, String]): Map[String, String]\n}\n\nsealed trait ServerHeaderExtractorLowPrio {\n\n  implicit val serverHeaderReturnCase = new ServerHeaderExtractor[HNil] {\n    def apply(agg: Map[String, String]): Map[String, String] = agg\n  }\n\n  implicit def serverHeaderIgnoreCase[H, T <: HList](implicit next: ServerHeaderExtractor[T]) = new ServerHeaderExtractor[H :: T] {\n    def apply(agg: Map[String, String]): Map[String, String] = next(agg)\n  }\n}\n\nobject ServerHeaderExtractor extends ServerHeaderExtractorLowPrio {\n\n  implicit def serverHeaderExtractCase[K, V, T <: HList]\n      (implicit kWit: Witness.Aux[K], kShow: WitnessToString[K], vWit: Witness.Aux[V], vShow: WitnessToString[V], next: ServerHeaderExtractor[T]) = \n    new ServerHeaderExtractor[ServerHeaderSend[K, V] :: T] {\n      def apply(agg: Map[String, String]): Map[String, String] = {\n        val key   = kShow.show(kWit.value)\n        val value = vShow.show(vWit.value)\n\n        next(agg + (key -> value))\n      }\n    }\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/ServerManager.scala",
    "content": "package typedapi.server\n\nimport scala.annotation.tailrec\n\nfinal case class ServerManager[S](server: S, host: String, port: Int)\n\nobject ServerManager {\n\n  def mount[S, Req, Resp, Out](server: ServerManager[S], endpoints: List[Serve[Req, Resp]])(implicit mounting: MountEndpoints.Aux[S, Req, Resp, Out]): Out =\n    mounting(server, endpoints)\n}\n\ntrait MountEndpoints[S, Req, Resp] {\n\n  type Out\n\n  final def optionsHeaders(eps: List[Serve[Req, Resp]], eReq: EndpointRequest): Map[String, String] = {\n    @tailrec\n    def collect(serve: List[Serve[Req, Resp]], methods: List[String], headers: Map[String, String]): (List[String], Map[String, String]) = serve match {\n      case collection.immutable.::(endpoint, tail) => endpoint.options(eReq) match {\n        case Some((method, hds)) => collect(tail, method :: methods, hds ++ headers)\n        case _                   => collect(tail, methods, headers)\n      }\n\n      case Nil => (methods, headers)\n    }\n\n    val (methods, headers) = collect(eps, Nil, Map.empty)\n    \n    headers + ((\"Access-Control-Allow-Methods\", methods.mkString(\",\")))\n  }\n\n  def apply(server: ServerManager[S], endpoints: List[Serve[Req, Resp]]): Out\n}\n\nobject MountEndpoints {\n\n  type Aux[S, Req, Resp, Out0] = MountEndpoints[S, Req, Resp] { type Out = Out0 }\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/StatusCodes.scala",
    "content": "package typedapi.server\n\nfinal case class SuccessCode(statusCode: Int) extends AnyVal\nfinal case class ErrorCode(statusCode: Int) extends AnyVal\n\nfinal case class HttpError(code: ErrorCode, message: String)\n\nobject StatusCodes {\n\n  // success codes\n  final val Continue           = SuccessCode(100)\n  final val SwitchingProtocols = SuccessCode(101)\n  final val Processing         = SuccessCode(102)\n\n  final val Ok                          = SuccessCode(200)\n  final val Created                     = SuccessCode(201)\n  final val Accepted                    = SuccessCode(202)\n  final val NonAuthoritativeInformation = SuccessCode(203)\n  final val NoContent                   = SuccessCode(204)\n  final val ResetContent                = SuccessCode(205)\n  final val PartialContent              = SuccessCode(206)\n  final val MultiStatus                 = SuccessCode(207)\n  final val AlreadyReported             = SuccessCode(208)\n  final val IMUsed                      = SuccessCode(226)\n\n  final val MultipleChoices   = SuccessCode(300)\n  final val MovedPermanently  = SuccessCode(301)\n  final val Found             = SuccessCode(302)\n  final val SeeOther          = SuccessCode(303)\n  final val NotModified       = SuccessCode(304)\n  final val UseProxy          = SuccessCode(305)\n  final val TemporaryRedirect = SuccessCode(307)\n  final val PermanentRedirect = SuccessCode(308)\n\n  // error codes\n  final val BadRequest                      = ErrorCode(400)\n  final val Unauthorized                    = ErrorCode(401)\n  final val PaymentRequired                 = ErrorCode(402)\n  final val Forbidden                       = ErrorCode(403)\n  final val NotFound                        = ErrorCode(404)\n  final val MethodNotAllowed                = ErrorCode(405)\n  final val NotAcceptable                   = ErrorCode(406)\n  final val ProxyAuthenticationRequired     = ErrorCode(407)\n  final val RequestTimeout                  = ErrorCode(408)\n  final val Conflict                        = ErrorCode(409)\n  final val Gone                            = ErrorCode(410)\n  final val LengthRequired                  = ErrorCode(411)\n  final val PreconditionFailed              = ErrorCode(412)\n  final val PayloadTooLarge                 = ErrorCode(413)\n  final val RequestURITooLong               = ErrorCode(414)\n  final val UnsupportedMediaType            = ErrorCode(415)\n  final val RequestedRangeNotSatisfiable    = ErrorCode(416)\n  final val ExpectationFailed               = ErrorCode(417)\n  final val ImAteapot                       = ErrorCode(418)\n  final val MisdirectedRequest              = ErrorCode(421)\n  final val UnprocessableEntity             = ErrorCode(422)\n  final val Locked                          = ErrorCode(423)\n  final val FailedDependency                = ErrorCode(424)\n  final val UpgradeRequired                 = ErrorCode(426)\n  final val PreconditionRequired            = ErrorCode(428)\n  final val TooManyRequests                 = ErrorCode(429)\n  final val RequestHeaderFieldsTooLarge     = ErrorCode(431)\n  final val ConnectionClosedWithoutResult = ErrorCode(444)\n  final val UnavailableForLegalReasons      = ErrorCode(451)\n  final val ClientClosedRequest             = ErrorCode(499)\n\n  final val InternalServerError           = ErrorCode(500)\n  final val NotImplemented                = ErrorCode(501)\n  final val BadGateway                    = ErrorCode(502)\n  final val ServiceUnavailable            = ErrorCode(503)\n  final val GatewayTimeout                = ErrorCode(504)\n  final val HTTPVersionNotSupported       = ErrorCode(505)\n  final val VariantAlsoNegotiates         = ErrorCode(506)\n  final val InsufficientStorage           = ErrorCode(507)\n  final val LoopDetected                  = ErrorCode(508)\n  final val NotExtended                   = ErrorCode(510)\n  final val NetworkAuthenticationRequired = ErrorCode(511)\n  final val NetworkConnectTimeoutError    = ErrorCode(599)\n}\n"
  },
  {
    "path": "server/src/main/scala/typedapi/server/package.scala",
    "content": "package typedapi\n\nimport typedapi.shared._\nimport shapeless._\nimport shapeless.ops.hlist.Mapper\n\nimport scala.language.higherKinds\n\npackage object server extends TypeLevelFoldLeftLowPrio \n                      with TypeLevelFoldLeftListLowPrio \n                      with WitnessToStringLowPrio\n                      with ApiTransformer {\n\n  val SC = StatusCodes\n\n  type Result[A] = Either[HttpError, (SuccessCode, A)]\n\n  def successWith[A](code: SuccessCode)(a: A): Result[A] = Right(code -> a)\n  def success[A](a: A): Result[A] = successWith(StatusCodes.Ok)(a)\n\n  def errorWith[A](code: ErrorCode, message: String): Result[A] = Left(HttpError(code, message))\n\n  def derive[F[_]]: ExecutableDerivation[F] = new ExecutableDerivation[F]\n\n  def mount[S, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, F[_], FOut, Req, Resp, Out]\n      (server: ServerManager[S], endpoint: Endpoint[El, KIn, VIn, M, ROut, F, FOut])\n      (implicit executor: EndpointExecutor.Aux[Req, El, KIn, VIn, M, ROut, F, FOut, Resp], mounting: MountEndpoints.Aux[S, Req, Resp, Out]): Out =\n    mounting(server, List(new Serve[executor.R, executor.Out] {\n      def options(eReq: EndpointRequest): Option[(String, Map[String, String])] = {\n        endpoint.extractor(eReq, HNil) match {\n          case Right(_) => Some((endpoint.method, endpoint.headers))\n          case _        => None\n        }\n      }\n\n      def apply(req: executor.R, eReq: EndpointRequest): Either[ExtractionError, executor.Out] = executor(req, eReq, endpoint)\n    }))\n\n  def deriveAll[F[_]]: ExecutableCompositionDerivation[F] = new ExecutableCompositionDerivation[F]\n\n  object endpointToServe extends Poly1 {\n\n    implicit def default[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, F[_], FOut](implicit executor: EndpointExecutor[El, KIn, VIn, M, ROut, F, FOut]) = \n      at[Endpoint[El, KIn, VIn, M, ROut, F, FOut]] { endpoint =>\n        new Serve[executor.R, executor.Out] {\n          def options(eReq: EndpointRequest): Option[(String, Map[String, String])] = {\n            endpoint.extractor(eReq, HNil) match {\n              case Right(_) => Some((endpoint.method, endpoint.headers))\n              case _        => None\n            }\n          }\n\n          def apply(req: executor.R, eReq: EndpointRequest): Either[ExtractionError, executor.Out] = executor(req, eReq, endpoint)\n        }\n      }\n  }\n\n  def mount[S, End <: HList, Serv <: HList, Req, Resp, Out](server: ServerManager[S], end: End)(implicit mapper: Mapper.Aux[endpointToServe.type, End, Serv], toList: ServeToList[Serv, Req, Resp], mounting: MountEndpoints.Aux[S, Req, Resp, Out]): Out =\n    mounting(server, toList(end.map(endpointToServe)))\n}\n"
  },
  {
    "path": "server/src/test/scala/typedapi/server/ApiToEndpointLinkSpec.scala",
    "content": "package typedapi.server\n\nimport typedapi.dsl._\nimport shapeless._\n\nimport org.specs2.mutable.Specification\n\nfinal class ApiToEndpointLinkSpec extends Specification {\n\n  import StatusCodes._\n\n  case class Foo(name: String)\n\n  \"link api definitions to endpoint functions\" >> { \n    val Api = := :> \"find\" :> typedapi.dsl.Segment[String]('name) :> \n                    Query[Int]('limit) :> \n                    Client.Header('hello, 'world) :> \n                    Server.Send('foo, 'bar) :> Server.Match[String](\"hi\") :>\n                    Get[Json, List[Foo]]\n\n    val endpoint0 = derive[Option](Api).from((name, limit, hi) => Some(successWith(Ok)(List(Foo(name)).take(limit))))\n    endpoint0(\"john\" :: 10 :: Map(\"hi\" -> \"whats\", \"hi-ho\" -> \"up\") :: HNil) === Some(Right(Ok -> List(Foo(\"john\"))))\n    endpoint0.headers == Map(\"foo\" -> \"bar\")\n    endpoint0.method == \"GET\"\n  }\n}\n"
  },
  {
    "path": "server/src/test/scala/typedapi/server/RouteExtractorSpec.scala",
    "content": "package typedapi.server\n\nimport typedapi.dsl._\nimport typedapi.shared._\nimport shapeless.{HList, HNil, Lazy}\nimport org.specs2.mutable.Specification\n\nfinal class RouteExtractorSpec extends Specification {\n\n  case class Foo(name: String)\n\n  def extract[H <: HList, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, Out]\n    (api: ApiTypeCarrier[H])\n    (implicit folder: Lazy[TypeLevelFoldLeft.Aux[H, Unit, (El, KIn, VIn, M, Out)]],\n              extractor: RouteExtractor.Aux[El, KIn, VIn, M, HNil, ROut]): RouteExtractor.Aux[El, KIn, VIn, M, HNil, ROut] = extractor\n\n  \"determine routes defined by requests and extract included data (segments, queries, headers)\" >> {\n    \"no data\" >> {\n      val ext = extract(:= :> \"hello\" :> \"world\" :> Get[Json, Foo])\n      \n      ext(EndpointRequest(\"GET\", List(\"hello\", \"world\"), Map.empty, Map.empty), HNil) === Right(HNil)\n      ext(EndpointRequest(\"GET\", List(\"hello\", \"wrong\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n      ext(EndpointRequest(\"GET\", List(\"hello\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n      ext(EndpointRequest(\"GET\", Nil, Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n    }\n\n    \"segments\" >> {\n      val ext = extract(:= :> \"foo\" :> Segment[Int]('age) :> Get[Json, Foo])\n\n      ext(EndpointRequest(\"GET\", List(\"foo\", \"0\"), Map.empty, Map.empty), HNil) === Right(0 :: HNil)\n      ext(EndpointRequest(\"GET\", List(\"foo\", \"wrong\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n      ext(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n      ext(EndpointRequest(\"GET\", Nil, Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n    }\n\n    \"queries\" >> {\n      val ext0 = extract(:= :> \"foo\" :> Query[Int]('age) :> Get[Json, Foo])\n\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map(\"age\" -> List(\"0\")), Map.empty), HNil) === Right(0 :: HNil)\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map(\"age\" -> List(\"wrong\")), Map.empty), HNil) === RouteExtractor.BadRequestE(\"query 'age' has not type Int\")\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map(\"wrong\" -> List(\"0\")), Map.empty), HNil) === RouteExtractor.BadRequestE(\"missing query 'age'\")\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map.empty), HNil) === RouteExtractor.BadRequestE(\"missing query 'age'\")\n      ext0(EndpointRequest(\"GET\", List(\"foo\", \"bar\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n\n      val ext1 = extract(:= :> \"foo\" :> Query[Option[Int]]('age) :> Get[Json, Foo])\n\n      ext1(EndpointRequest(\"GET\", List(\"foo\"), Map(\"age\" -> List(\"0\")), Map.empty), HNil) === Right(Some(0) :: HNil)\n      ext1(EndpointRequest(\"GET\", List(\"foo\"), Map(\"wrong\" -> List(\"0\")), Map.empty), HNil) === Right(None :: HNil)\n\n      val ext2 = extract(:= :> \"foo\" :> Query[List[Int]]('age) :> Get[Json, Foo])\n\n      ext2(EndpointRequest(\"GET\", List(\"foo\"), Map(\"age\" -> List(\"0\", \"1\")), Map.empty), HNil) === Right(List(0, 1) :: HNil)\n      ext2(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map.empty), HNil) === Right(Nil :: HNil)\n    }\n\n    \"headers\" >> {\n      val ext0 = extract(:= :> \"foo\" :> Header[Int]('age) :> Get[Json, Foo])\n\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"age\" -> \"0\")), HNil) === Right(0 :: HNil)\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"age\" -> \"wrong\")), HNil) === RouteExtractor.BadRequestE(\"header 'age' has not type Int\")\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"wrong\" -> \"0\")), HNil) === RouteExtractor.BadRequestE(\"missing header 'age'\")\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map.empty), HNil) === RouteExtractor.BadRequestE(\"missing header 'age'\")\n      ext0(EndpointRequest(\"GET\", List(\"foo\", \"bar\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n\n      val ext2 = extract(:= :> \"foo\" :> Header[Option[Int]]('age) :> Get[Json, Foo])\n\n      ext2(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"age\" -> \"0\")), HNil) === Right(Some(0) :: HNil)\n      ext2(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map.empty), HNil) === Right(None :: HNil)\n\n      val ext3 = extract(:= :> \"foo\" :> Header(\"Accept\", \"*\") :> Get[Json, Foo])\n\n      ext3(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"accept\" -> \"*\")), HNil) === Right(HNil)\n      ext3(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"wrong\" -> \"*\")), HNil) === RouteExtractor.BadRequestE(\"missing header 'Accept'\")\n      ext3(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"accept\" -> \"wrong\")), HNil) === RouteExtractor.BadRequestE(\"header 'Accept' has unexpected value 'wrong' - expected '*'\")\n\n      val ext4 = extract(:= :> \"foo\" :> Server.Send(\"Accept\", \"*\") :> Get[Json, Foo])\n\n      ext4(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map.empty), HNil) === Right(HNil)\n\n      val ext6 = extract(:= :> \"foo\" :> Server.Match[Int](\"age\") :> Get[Json, Foo])\n\n      ext6(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"age\" -> \"0\")), HNil) === Right(Map(\"age\" ->0) :: HNil)\n      ext6(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"age-and-what-not\" -> \"0\")), HNil) === Right(Map(\"age-and-what-not\" -> 0) :: HNil)\n      ext6(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"nope\" -> \"0\")), HNil) === Right(Map.empty :: HNil)\n      ext6(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map(\"age-\" -> \"hello\")), HNil) === RouteExtractor.BadRequestE(\"header 'age-' has not type Int\")\n    }\n\n    \"body type\" >> {\n      val ext0 = extract(:= :> ReqBody[Json, Foo] :> Put[Json, Foo])\n\n      ext0(EndpointRequest(\"PUT\", Nil, Map.empty, Map.empty), HNil) === Right((BodyType[Foo], HNil))\n      ext0(EndpointRequest(\"PUT\", List(\"foo\", \"bar\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n      ext0(EndpointRequest(\"OPTIONS\", List(\"foo\", \"bar\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n\n      val ext1 = extract(:= :> ReqBody[Json, Foo] :> Post[Json, Foo])\n\n      ext1(EndpointRequest(\"POST\", Nil, Map.empty, Map.empty), HNil) === Right((BodyType[Foo], HNil))\n      ext1(EndpointRequest(\"OPTIONS\", Nil, Map.empty, Map.empty), HNil) === Right((BodyType[Foo], HNil))\n    }\n\n    \"methods\" >> {\n      val ext0 = extract(:= :> Get[Json, Foo])\n\n      ext0(EndpointRequest(\"GET\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n      ext0(EndpointRequest(\"WRONG\", Nil, Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map.empty, Map.empty), HNil) === RouteExtractor.NotFoundE\n      ext0(EndpointRequest(\"OPTIONS\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n\n      val ext1 = extract(:= :> Put[Json, Foo])\n\n      ext1(EndpointRequest(\"PUT\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n      ext1(EndpointRequest(\"OPTIONS\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n\n      val ext2 = extract(:= :> Post[Json, Foo])\n\n      ext2(EndpointRequest(\"POST\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n      ext2(EndpointRequest(\"OPTIONS\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n\n      val ext3 = extract(:= :> Delete[Json, Foo])\n\n      ext3(EndpointRequest(\"DELETE\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n      ext3(EndpointRequest(\"OPTIONS\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n    }\n\n    \"combinations\" >> {\n      val ext0 = extract(:= :> \"foo\" :> Query[Int]('age) :> Header[String]('id) :> Get[Json, Foo])\n\n      ext0(EndpointRequest(\"GET\", List(\"foo\"), Map(\"age\" -> List(\"0\")), Map(\"id\" -> \"john\")), HNil) === Right(0 :: \"john\" :: HNil)\n\n      val ext1 = extract(:= :> Get[Json, Foo])\n\n      ext1(EndpointRequest(\"GET\", Nil, Map.empty, Map.empty), HNil) === Right(HNil)\n    }\n  }\n}\n"
  },
  {
    "path": "server/src/test/scala/typedapi/server/ServeAndMountSpec.scala",
    "content": "package typedapi.server\n\nimport typedapi.dsl._\nimport typedapi.shared.MethodType\nimport shapeless.{HList, HNil, ::}\nimport shapeless.ops.hlist.{Prepend, Mapper}\nimport org.specs2.mutable.Specification\n\nimport scala.language.higherKinds\n\nfinal class ServeAndMountSpec extends Specification {\n\n  import StatusCodes._\n\n  case class Foo(name: String)\n\n  sealed trait Req\n  case class TestRequest(uri: List[String], queries: Map[String, List[String]], headers: Map[String, String]) extends Req\n  case class TestRequestWithBody[Bd](uri: List[String], queries: Map[String, List[String]], headers: Map[String, String], body: Bd) extends Req\n\n  case class TestResponse(raw: Any)\n\n  implicit def execNoBodyId[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, FOut] = \n    new NoReqBodyExecutor[El, KIn, VIn, M, Option, FOut] {\n      type R = Req\n      type Out = TestResponse\n\n      def apply(req: Req, eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, VIn, Option, FOut]): Either[ExtractionError, Out] =\n        extract(eReq, endpoint).right.map { extracted => \n          TestResponse(execute(extracted, endpoint))\n        }\n    }\n\n  implicit def execWithBody[El <: HList, KIn <: HList, VIn <: HList, Bd, M <: MethodType, ROut <: HList, POut <: HList, FOut](implicit _prepend: Prepend.Aux[ROut, Bd :: HNil, POut], _eqProof: POut =:= VIn) = \n    new ReqBodyExecutor[El, KIn, VIn, Bd, M, ROut, POut, Option, FOut] {\n      type R = Req\n      type Out = TestResponse\n\n      implicit val prepend = _prepend\n      implicit def eqProof = _eqProof\n\n      def apply(req: Req, eReq: EndpointRequest, endpoint: Endpoint[El, KIn, VIn, M, (BodyType[Bd], ROut), Option, FOut]): Either[ExtractionError, Out] =\n        extract(eReq, endpoint).right.map { case (_, extracted) => \n          TestResponse(execute(extracted, req.asInstanceOf[TestRequestWithBody[Bd]].body, endpoint))\n        }\n    }\n\n  def toList[El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, ROut, F[_], FOut](endpoint: Endpoint[El, KIn, VIn, M, ROut, F, FOut])\n                                                                                        (implicit executor: EndpointExecutor[El, KIn, VIn, M, ROut, F, FOut]): List[Serve[executor.R, executor.Out]] = \n    List(new Serve[executor.R, executor.Out] {\n      def options(eReq: EndpointRequest): Option[(String, Map[String, String])] = {\n        endpoint.extractor(eReq, HNil) match {\n          case Right(_) => Some((endpoint.method, endpoint.headers))\n          case _        => None\n        }\n      }\n\n      def apply(req: executor.R, eReq: EndpointRequest): Either[ExtractionError, executor.Out] = executor(req, eReq, endpoint)\n    })\n\n  def toList[End <: HList, Serv <: HList](end: End)(implicit mapper: Mapper.Aux[endpointToServe.type, End, Serv], s: ServeToList[Serv, Req, TestResponse]): List[Serve[Req, TestResponse]] =\n    s(end.map(endpointToServe))\n\n  \"serve endpoints as simple Request -> Response functions and mount them into a server\" >> {\n    \"serve single endpoint and no body\" >> {\n      val Api      = := :> \"find\" :> \"user\" :> Segment[String]('name) :> Query[Int]('sortByAge) :> Get[Json, List[Foo]]\n      val endpoint = derive[Option](Api).from((name, sortByAge) => Some(successWith(Ok)(List(Foo(name)))))\n      val served   = toList(endpoint)\n\n      val req  = TestRequest(List(\"find\", \"user\", \"joe\"), Map(\"sortByAge\" -> List(\"1\")), Map.empty)\n      val eReq = EndpointRequest(\"GET\", req.uri, req.queries, req.headers)\n\n      served.head(req, eReq) === Right(TestResponse(Some(Right(Ok -> List(Foo(\"joe\"))))))\n    }\n\n    \"check if route exists and return method\" >> {\n      val Api      = := :> \"find\" :> \"user\" :> Segment[String]('name) :> Query[Int]('sortByAge) :> Server.Send(\"Hello\", \"*\") :> Get[Json, List[Foo]]\n      val endpoint = derive[Option](Api).from((name, sortByAge) => Some(successWith(Ok)(List(Foo(name)))))\n      val served   = toList(endpoint)\n\n      val req0  = TestRequest(List(\"find\", \"user\", \"joe\"), Map(\"sortByAge\" -> List(\"1\")), Map.empty)\n      val eReq0 = EndpointRequest(\"GET\", req0.uri, req0.queries, req0.headers)\n\n      served.head.options(eReq0) === Some((\"GET\", Map((\"Hello\", \"*\"))))\n\n      val eReq1 = EndpointRequest(\"POST\", req0.uri, req0.queries, req0.headers)\n\n      served.head.options(eReq1) === None\n    }\n\n    \"serve single endpoint and with body\" >> {\n      val Api      = := :> \"find\" :> \"user\" :> Segment[String]('name) :> ReqBody[Json, Foo] :> Post[Json, List[Foo]]\n      val endpoint = derive[Option](Api).from((name, body) => Some(successWith(Ok)(List(Foo(name), body))))\n      val served   = toList(endpoint)\n\n      val req  = TestRequestWithBody(List(\"find\", \"user\", \"joe\"), Map.empty, Map.empty, Foo(\"jim\"))\n      val eReq = EndpointRequest(\"POST\", req.uri, req.queries, req.headers)\n\n      served.head(req, eReq) === Right(TestResponse(Some(Right(Ok -> List(Foo(\"joe\"), Foo(\"jim\"))))))\n    }\n\n    \"serve multiple endpoints\" >> {\n      val Api = \n        (:= :> \"find\" :> \"user\" :> Segment[String]('name) :> Query[Int]('sortByAge) :> Get[Json, List[Foo]]) :|:\n        (:= :> \"create\" :> \"user\" :> ReqBody[Json, Foo] :> Post[Json, Foo])\n\n      def find(name: String, age: Int): Option[Result[List[Foo]]] = Some(successWith(Ok)(List(Foo(name))))\n      def create(foo: Foo): Option[Result[Foo]] = Some(successWith(Ok)(foo))\n\n      val endpoints = deriveAll[Option](Api).from(find _, create _)\n\n      val served = toList(endpoints)\n\n      val req  = TestRequest(List(\"find\", \"user\", \"joe\"), Map(\"sortByAge\" -> List(\"1\")), Map.empty)\n      val eReq = EndpointRequest(\"GET\", req.uri, req.queries, req.headers)\n\n      served.head(req, eReq) === Right(TestResponse(Some(Right(Ok -> List(Foo(\"joe\"))))))\n    }\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/dsl/ApiDsl.scala",
    "content": "package typedapi.dsl\n\nimport typedapi.shared._\nimport shapeless._\n\nsealed trait ApiList[H <: HList]\n\n/** Basic operations. */\nsealed trait MethodOps[H <: HList] {\n\n  def :>[MT <: MediaType, A](body: TypeCarrier[ReqBodyElement[MT, A]]): WithBodyCons[MT, A, H] = WithBodyCons()\n  def :>[M <: MethodElement](method: TypeCarrier[M]): ApiTypeCarrier[M :: H] = ApiTypeCarrier()\n}\n\nsealed trait PathOps[H <: HList] {\n\n  def :>[S](path: Witness.Lt[S]): PathCons[PathElement[S] :: H] = PathCons()\n  def :>[K, V](segment: TypeCarrier[SegmentParam[K, V]]): SegmentCons[SegmentParam[K, V] :: H] = SegmentCons()\n}\n\nsealed trait HeaderOps[H <: HList] {\n\n  def :>[K, V](header: TypeCarrier[HeaderParam[K, V]]): InputHeaderCons[HeaderParam[K, V] :: H] = InputHeaderCons()\n  def :>[K, V](fixed: TypeCarrier[FixedHeaderElement[K, V]]): FixedHeaderCons[FixedHeaderElement[K, V] :: H] = FixedHeaderCons()\n\n  def :>[K, V](client: TypeCarrier[ClientHeaderElement[K, V]]): ClientHeaderElCons[ClientHeaderElement[K, V] :: H] = ClientHeaderElCons()\n  def :>[K, V](client: TypeCarrier[ClientHeaderParam[K, V]]): ClientHeaderParamCons[ClientHeaderParam[K, V] :: H] = ClientHeaderParamCons()\n  def :>[V](client: TypeCarrier[ClientHeaderCollParam[V]]): ClientHeaderCollParamCons[ClientHeaderCollParam[V] :: H] = ClientHeaderCollParamCons()\n\n  def :>[K, V](server: TypeCarrier[ServerHeaderMatchParam[K, V]]): ServerHeaderMatchParamCons[ServerHeaderMatchParam[K, V] :: H] = ServerHeaderMatchParamCons()\n  def :>[K, V](server: TypeCarrier[ServerHeaderSendElement[K, V]]): ServerHeaderSendElCons[ServerHeaderSendElement[K, V] :: H] = ServerHeaderSendElCons()\n}\n\n/** Initial element with empty api description. */\ncase object EmptyCons extends PathOps[HNil] with HeaderOps[HNil] with MethodOps[HNil] with ApiList[HNil] {\n\n  def :>[K, V](query: TypeCarrier[QueryParam[K, V]]): QueryCons[QueryParam[K, V] :: HNil] = QueryCons()\n}\n\n/** Last set element is a path. */\nfinal case class PathCons[H <: HList]() extends PathOps[H] with HeaderOps[H] with MethodOps[H] with ApiList[H] {\n  \n  def :>[K, V](query: TypeCarrier[QueryParam[K, V]]): QueryCons[QueryParam[K, V] :: H] = QueryCons()\n}\n\n/** Last set element is a segment. */\nfinal case class SegmentCons[H <: HList]() extends PathOps[H] with HeaderOps[H] with MethodOps[H] with ApiList[H] {\n\n  def :>[K, V](query: TypeCarrier[QueryParam[K, V]]): QueryCons[QueryParam[K, V] :: H] = QueryCons()\n}\n\n/** Last set element is a query parameter. */\nfinal case class QueryCons[H <: HList]() extends HeaderOps[H] with MethodOps[H] with ApiList[H] {\n\n  def :>[K, V](query: TypeCarrier[QueryParam[K, V]]): QueryCons[QueryParam[K, V] :: H] = QueryCons()\n}\n\n/** Last set element is a header. */\nsealed trait HeaderCons[H <: HList] extends HeaderOps[H] with MethodOps[H] with ApiList[H]\n\nfinal case class InputHeaderCons[H <: HList]() extends HeaderCons[H]\nfinal case class FixedHeaderCons[H <: HList]() extends HeaderCons[H]\nfinal case class ClientHeaderElCons[H <: HList]() extends HeaderCons[H]\nfinal case class ClientHeaderParamCons[H <: HList]() extends HeaderCons[H]\nfinal case class ClientHeaderCollParamCons[H <: HList]() extends HeaderCons[H]\nfinal case class ServerHeaderMatchParamCons[H <: HList]() extends HeaderCons[H]\nfinal case class ServerHeaderSendElCons[H <: HList]() extends HeaderCons[H]\n\n/** Last set element is a request body. */\nfinal case class WithBodyCons[BMT <: MediaType, Bd, H <: HList]() extends ApiList[H] {\n\n  def :>[M <: MethodElement](method: TypeCarrier[M])(implicit out: MethodToReqBody[M, BMT, Bd]): ApiTypeCarrier[out.Out :: H] = ApiTypeCarrier()\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/dsl/package.scala",
    "content": "package typedapi\n\nimport typedapi.shared._\n\npackage object dsl extends MethodToReqBodyLowPrio with MethodToStringLowPrio {\n\n  val MediaTypes = typedapi.shared.MediaTypes\n  val MT         = typedapi.shared.MediaTypes\n\n  def := = EmptyCons\n\n  def Segment[V] = new PairTypeFromWitnessKey[SegmentParam, V]\n  def Query[V]   = new PairTypeFromWitnessKey[QueryParam, V]\n  def Header[V]  = new PairTypeFromWitnessKey[HeaderParam, V]\n  def Header     = new PairTypeFromWitnesses[FixedHeaderElement]\n\n  object Client {\n\n    def Header    = new PairTypeFromWitnesses[ClientHeaderElement]\n    def Header[V] = new PairTypeFromWitnessKey[ClientHeaderParam, V]\n    def Coll[V]   = TypeCarrier[ClientHeaderCollParam[V]]()\n  }\n\n  object Server {\n\n    def Send      = new PairTypeFromWitnesses[ServerHeaderSendElement]\n    def Match[V]  = new PairTypeFromWitnessKey[ServerHeaderMatchParam, V]\n  }\n\n  type Json  = MT.`Application/json`\n  type Plain = MT.`Text/plain`\n\n  def ReqBody[MT <: MediaType, A] = TypeCarrier[ReqBodyElement[MT, A]]()\n  def Get[MT <: MediaType, A]     = TypeCarrier[GetElement[MT, A]]()\n  def Put[MT <: MediaType, A]     = TypeCarrier[PutElement[MT, A]]()\n  def Post[MT <: MediaType, A]    = TypeCarrier[PostElement[MT, A]]()\n  def Delete[MT <: MediaType, A]  = TypeCarrier[DeleteElement[MT, A]]()\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/package.scala",
    "content": "\nimport typedapi.shared._\nimport shapeless._\nimport shapeless.ops.hlist.Prepend\n\npackage object typedapi extends MethodToReqBodyLowPrio with MethodToStringLowPrio {\n\n  val MediaTypes = typedapi.shared.MediaTypes\n  val MT         = typedapi.shared.MediaTypes\n\n  val Root       = PathListBuilder[HNil]()\n  def Segment[V] = new PairTypeFromWitnessKey[SegmentParam, V]\n\n  val Queries   = QueryListBuilder[HNil]()\n  val NoQueries = Queries\n\n  val Headers      = HeaderListBuilder[HNil]()\n  val NoHeaders    = Headers\n\n  def ReqBody[MT <: MediaType, A] = TypeCarrier[ReqBodyElement[MT, A]]()\n  def Get[MT <: MediaType, A]     = TypeCarrier[GetElement[MT, A]]()\n  def Put[MT <: MediaType, A]     = TypeCarrier[PutElement[MT, A]]()\n  def Post[MT <: MediaType, A]    = TypeCarrier[PostElement[MT, A]]()\n  def Delete[MT <: MediaType, A]  = TypeCarrier[DeleteElement[MT, A]]()\n\n  type Json  = MT.`Application/json`\n  type Plain = MT.`Text/plain`\n\n  def api[M <: MethodElement, P <: HList, Q <: HList, H <: HList, Prep <: HList, Api <: HList]\n      (method: TypeCarrier[M], path: PathListBuilder[P] = Root, queries: QueryListBuilder[Q] = NoQueries, headers: HeaderListBuilder[H] = NoHeaders)\n      (implicit prepQP: Prepend.Aux[Q, P, Prep], prepH: Prepend.Aux[H, Prep, Api]): ApiTypeCarrier[M :: Api] = ApiTypeCarrier()\n\n  def apiWithBody[M <: MethodElement, P <: HList, Q <: HList, H <: HList, Prep <: HList, Api <: HList, BMT <: MediaType, Bd]\n      (method: TypeCarrier[M], body: TypeCarrier[ReqBodyElement[BMT, Bd]], path: PathListBuilder[P] = Root, queries: QueryListBuilder[Q] = NoQueries, headers: HeaderListBuilder[H] = NoHeaders)\n      (implicit prepQP: Prepend.Aux[Q, P, Prep], prepH: Prepend.Aux[H, Prep, Api], m: MethodToReqBody[M, BMT, Bd]): ApiTypeCarrier[m.Out :: Api] = ApiTypeCarrier()\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/ApiElement.scala",
    "content": "package typedapi.shared\n\nimport scala.annotation.implicitNotFound\n\nsealed trait ApiElement\n\n/** Type-container providing the singleton-type of an static path element */\nsealed trait PathElement[P]\n\n/** Type-container providing the name (singleton) and value type for a path parameter. */\nsealed trait SegmentParam[K, V] extends ApiElement\n\n/** Type-container providing the name (singleton) and value type for a query parameter. */\nsealed trait QueryParam[K, V] extends ApiElement\n\n/** Type-container providing the name (singleton) and value type for a header parameter. */\nsealed trait HeaderParam[K, V] extends ApiElement\n\n/** Type-container providing the name (singleton) and value type for a static header element. */\nsealed trait FixedHeaderElement[K, V] extends ApiElement\n/** Type-container providing the name (singleton) and value type for a static header element only used for the client. */\nsealed trait ClientHeaderElement[K, V] extends ApiElement\n/** Type-container providing the name (singleton) and value type for a header parameter only used for the client. */\nsealed trait ClientHeaderParam[K, V] extends ApiElement\n/** Type-container providing a collection of headers (Map[String, V]) only used for the client. */\nsealed trait ClientHeaderCollParam[V] extends ApiElement\n/** Type-container providing the name (singleton) and value type for a static header element sent by server. */\nsealed trait ServerHeaderSendElement[K, V] extends ApiElement\n/** Type-container providing the name (singleton) and value type describing a sub-string headers have to match only used for the server. */\nsealed trait ServerHeaderMatchParam[K, V] extends ApiElement\n\n/** Type-container providing the media-type and value type for a request body. */\nsealed trait ReqBodyElement[MT <: MediaType, A] extends ApiElement\n\ntrait MethodElement extends ApiElement\n/** Type-container representing a GET operation with a media-type and value type for the result. */\nsealed trait GetElement[MT <: MediaType, A] extends MethodElement\n/** Type-container representing a PUT operation with a media-type and value type for the result. */\nsealed trait PutElement[MT <: MediaType, A] extends MethodElement\n/** Type-container representing a PUT operation with a media-type and value type for the result and a body. */\nsealed trait PutWithBodyElement[BMT <: MediaType, Bd, MT <: MediaType, A] extends MethodElement\n/** Type-container representing a POST operation with a media-type and value type for the result. */\nsealed trait PostElement[MT <: MediaType, A] extends MethodElement\n/** Type-container representing a POST operation with a media-type and value type for the result and a body. */\nsealed trait PostWithBodyElement[BMT <: MediaType, Bd, MT <: MediaType, A] extends MethodElement\n/** Type-container representing a DELETE operation with a media-type and value type for the result. */\nsealed trait DeleteElement[MT <: MediaType, A] extends MethodElement\n\n@implicitNotFound(\"\"\"You try to add a request body to a method which doesn't expect one.\n\nmethod: ${M}\n\"\"\")\ntrait MethodToReqBody[M <: MethodElement, MT <: MediaType, Bd] {\n\n  type Out <: MethodElement\n}\n\ntrait MethodToReqBodyLowPrio {\n\n  implicit def reqBodyForPut[MT <: MediaType, A, BMT <: MediaType, Bd] = new MethodToReqBody[PutElement[MT, A], BMT, Bd] {\n    type Out = PutWithBodyElement[BMT, Bd, MT, A]\n  }\n\n  implicit def reqBodyForPost[MT <: MediaType, A, BMT <: MediaType, Bd] = new MethodToReqBody[PostElement[MT, A], BMT, Bd] {\n    type Out = PostWithBodyElement[BMT, Bd, MT, A]\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/ApiList.scala",
    "content": "package typedapi.shared\n\nimport shapeless._\n\n/** Typecarrier to construct a complete path description from [[PathElement]]s and [[SegmentParam]]s. */\nfinal case class PathListBuilder[P <: HList]() {\n\n  def /[S](path: Witness.Lt[S]): PathListBuilder[PathElement[S] :: P] = PathListBuilder()\n  def /[K, V](segment: TypeCarrier[SegmentParam[K, V]]): PathListBuilder[SegmentParam[K, V] :: P] = PathListBuilder()\n}\n\n/** Typecarrier to construct a set of queries from [[QueryParam]]s. */\nfinal case class QueryListBuilder[Q <: HList]() {\n\n  final class WitnessDerivation[V] {\n    def apply[K](wit: Witness.Lt[K]): QueryListBuilder[QueryParam[K, V] :: Q] = QueryListBuilder()\n  }\n\n  def add[V]: WitnessDerivation[V] = new WitnessDerivation[V]\n}\n\n/** Typecarrier to construct a set of headers from [[HeaderParam]]s, [[FixedHeaderElement]]s, [[ClientHeaderElement]]s, \n    [[ServerHeaderSendElement]]s and [ServerHeaderMatchParam]]s. */\nfinal case class HeaderListBuilder[H <: HList]() {\n\n  final class WitnessDerivation[V] {\n    def apply[K](wit: Witness.Lt[K]): HeaderListBuilder[HeaderParam[K, V] :: H] = HeaderListBuilder()\n  }\n  def add[V]: WitnessDerivation[V] = new WitnessDerivation[V]\n  \n  def add[K, V](kWit: Witness.Lt[K], vWit: Witness.Lt[V]): HeaderListBuilder[FixedHeaderElement[K, V] :: H] = HeaderListBuilder()\n\n  final class ClientWitnessDerivation[V] {\n    def apply[K](wit: Witness.Lt[K]): HeaderListBuilder[ClientHeaderParam[K, V] :: H] = HeaderListBuilder()\n  }\n  def client[V]: ClientWitnessDerivation[V] = new ClientWitnessDerivation[V]\n  \n  def client[K, V](kWit: Witness.Lt[K], vWit: Witness.Lt[V]): HeaderListBuilder[ClientHeaderElement[K, V] :: H] = HeaderListBuilder()\n\n  def clientColl[V]: HeaderListBuilder[ClientHeaderCollParam[V] :: H] = HeaderListBuilder()\n\n  final class ServerMatchWitnessDerivation[V] {\n    def apply[K](wit: Witness.Lt[K]): HeaderListBuilder[ServerHeaderMatchParam[K, V] :: H] = HeaderListBuilder()\n  }\n  def serverMatch[V]: ServerMatchWitnessDerivation[V] = new ServerMatchWitnessDerivation[V]\n\n  def serverSend[K, V](kWit: Witness.Lt[K], vWit: Witness.Lt[V]): HeaderListBuilder[ServerHeaderSendElement[K, V] :: H] = HeaderListBuilder()\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/ApiTransformer.scala",
    "content": "package typedapi.shared\n\nimport shapeless._\nimport shapeless.labelled.FieldType\n\nimport scala.annotation.implicitNotFound\n\ntrait ApiOp\n\nsealed trait SegmentInput extends ApiOp\nsealed trait QueryInput extends ApiOp\nsealed trait HeaderInput extends ApiOp\n\nsealed trait FixedHeader[K, V] extends ApiOp\nsealed trait ClientHeader[K, V] extends ApiOp\nsealed trait ClientHeaderInput extends ApiOp\nsealed trait ClientHeaderCollInput extends ApiOp\nsealed trait ServerHeaderSend[K, V] extends ApiOp\nsealed trait ServerHeaderMatchInput extends ApiOp\n\ntrait MethodType extends ApiOp\nsealed trait GetCall extends MethodType\nsealed trait PutCall extends MethodType\nsealed trait PutWithBodyCall extends MethodType\nsealed trait PostCall extends MethodType\nsealed trait PostWithBodyCall extends MethodType\nsealed trait DeleteCall extends MethodType\n\n/** Transforms a [[MethodType]] to a `String`. */\n@implicitNotFound(\"Missing String transformation for this method = ${M}.\")\ntrait MethodToString[M <: MethodType] {\n\n  def show: String\n}\n\ntrait MethodToStringLowPrio {\n\n  implicit val getToStr      = new MethodToString[GetCall] { val show = \"GET\" }\n  implicit val putToStr      = new MethodToString[PutCall] { val show = \"PUT\" }\n  implicit val putBodyToStr  = new MethodToString[PutWithBodyCall] { val show = \"PUT\" }\n  implicit val postToStr     = new MethodToString[PostCall] { val show = \"POST\" }\n  implicit val postBodyToStr = new MethodToString[PostWithBodyCall] { val show = \"POST\" }\n  implicit val deleteToStr   = new MethodToString[DeleteCall] { val show = \"DELETE\" }\n}\n\n/** Tranforms API type shape into five distinct types:\n  *  - El:  elements of the API (path elements, segment/query/header input placeholder, etc.)\n  *  - KIn: expected input key types (from parameters)\n  *  - VIn: expected input value types (from parameters)\n  *  - M:   method type \n  *  - Out: output type\n  * \n  * ```\n  * val api: TypeCarrier[Get[Json, Foo] :: Segment[\"name\".type, String] :: \"find\".type :: HNil]\n  * val trans: (\"name\".type :: SegmentInput :: HNil, \"name\".type :: HNil, String :: HNil], Field[Json, GetCall], Foo)\n  * ```\n  */\ntrait ApiTransformer {\n\n  import TypeLevelFoldFunction.at\n\n  implicit def pathElementTransformer[S, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[PathElement[S], (El, KIn, VIn, M, Out), (S :: El, KIn, VIn, M, Out)]\n\n  implicit def segmentParamTransformer[S, A, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[SegmentParam[S, A], (El, KIn, VIn, M, Out), (SegmentInput :: El, S :: KIn, A :: VIn, M, Out)]\n\n  implicit def queryParamTransformer[S, A, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[QueryParam[S, A], (El, KIn, VIn, M, Out), (QueryInput :: El, S :: KIn, A :: VIn, M, Out)]\n\n  implicit def queryListParamTransformer[S, A, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[QueryParam[S, List[A]], (El, KIn, VIn, M, Out), (QueryInput :: El, S :: KIn, List[A] :: VIn, M, Out)]\n\n  implicit def headerParamTransformer[S, A, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[HeaderParam[S, A], (El, KIn, VIn, M, Out), (HeaderInput :: El, S :: KIn, A :: VIn, M, Out)]\n\n  implicit def fixedHeaderElementTransformer[K, V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[FixedHeaderElement[K, V], (El, KIn, VIn, M, Out), (FixedHeader[K, V] :: El, KIn, VIn, M, Out)]\n\n  implicit def clientHeaderElementTransformer[K, V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[ClientHeaderElement[K, V], (El, KIn, VIn, M, Out), (ClientHeader[K, V] :: El, KIn, VIn, M, Out)]\n\n  implicit def clientHeaderParamTransformer[K, V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[ClientHeaderParam[K, V], (El, KIn, VIn, M, Out), (ClientHeaderInput :: El, K :: KIn, V :: VIn, M, Out)]\n\n  implicit def clientHeaderCollParamTransformer[V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[ClientHeaderCollParam[V], (El, KIn, VIn, M, Out), (ClientHeaderCollInput :: El, KIn, Map[String, V] :: VIn, M, Out)]\n\n  implicit def serverHeaderSendElementTransformer[K, V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[ServerHeaderSendElement[K, V], (El, KIn, VIn, M, Out), (ServerHeaderSend[K, V] :: El, KIn, VIn, M, Out)]\n\n  implicit def serverHeaderMatchParamTransformer[K, V, El <: HList, KIn <: HList, VIn <: HList, M <: MethodType, Out] = \n    at[ServerHeaderMatchParam[K, V], (El, KIn, VIn, M, Out), (ServerHeaderMatchInput :: El, K :: KIn, Map[String, V] :: VIn, M, Out)]\n\n  implicit def getTransformer[MT <: MediaType, A] = at[GetElement[MT, A], Unit, (HNil, HNil, HNil, GetCall, FieldType[MT, A])]\n\n  implicit def putTransformer[MT <: MediaType, A] = at[PutElement[MT, A], Unit, (HNil, HNil, HNil, PutCall, FieldType[MT, A])]\n\n  implicit def putWithBodyTransformer[BMT <: MediaType, Bd, MT <: MediaType, A] = \n    at[PutWithBodyElement[BMT, Bd, MT, A], Unit, (HNil, FieldType[BMT, BodyField.T] :: HNil, Bd :: HNil, PutWithBodyCall, FieldType[MT, A])]\n\n  implicit def postTransformer[MT <: MediaType, A] = at[PostElement[MT, A], Unit, (HNil, HNil, HNil, PostCall, FieldType[MT, A])]\n\n  implicit def postWithBodyTransformer[BMT <: MediaType, Bd, MT <: MediaType, A] = \n    at[PostWithBodyElement[BMT, Bd, MT, A], Unit, (HNil, FieldType[BMT, BodyField.T] :: HNil, Bd :: HNil, PostWithBodyCall, FieldType[MT, A])]\n\n  implicit def deleteTransformer[MT <: MediaType, A] = at[DeleteElement[MT, A], Unit, (HNil, HNil, HNil, DeleteCall, FieldType[MT, A])]\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/MediaTypes.scala",
    "content": "package typedapi.shared\n\ntrait MediaType { self =>\n  def value: String\n}\n\nobject MediaTypes {\n\n  case object NoMediaType extends MediaType {\n    val value = \"NO MEDIA TYPE\"\n  }\n\n  case object `application/atom+xml`                                                      extends MediaType {\n    val value = \"application/atom+xml\"\n  }\n  type `Application/atom+xml` = `application/atom+xml`.type                                                     \n  case object `application/base64`                                                        extends  MediaType {\n    val value = \"application/base64\"\n  }\n  type `Application/base64` = `application/base64`.type                                               \n  case object `application/excel`                                                         extends MediaType {\n    val value = \"application/excel\"\n  }\n  type `Application/excel` = `application/excel`.type                                                         \n  case object `application/font-woff`                                                     extends MediaType {\n    val value = \"application/font-woff\"\n  }\n  type `Application/font-woff` = `application/font-woff`.type                                                     \n  case object `application/gnutar`                                                        extends MediaType {\n    val value = \"application/gnutar\"\n  }\n  type `Application/gnutar` = `application/gnutar`.type                                                        \n  case object `application/java-archive`                                                  extends MediaType {\n    val value = \"application/java-archive\"\n  }\n  type `Application/java-archive` = `application/java-archive`.type                                                  \n  case object `application/javascript`                                                    extends MediaType {\n    val value = \"application/javascript\"\n  }\n  type `Application/javascript` = `application/javascript`.type                                                    \n  case object `application/json`                                                          extends MediaType {\n    val value = \"application/json\"\n  }\n  type `Application/json` = `application/json`.type                                                          \n  case object `application/json-patch+json`                                               extends MediaType {\n    val value = \"application/json-path+json\"\n  }\n  type `Application/json-patch+json` = `application/json-patch+json`.type                                               \n  case object `application/grpc+proto`                                                    extends MediaType {\n    val value = \"application/grpc+proto\"\n    type `Application/grpc+proto` = `application/grpc+proto`.type                                                    \n  }\n  case object `application/lha`                                                           extends MediaType {\n    val value = \"application/lha\"\n  }\n  type `Application/lha` = `application/lha`.type                                                           \n  case object `application/lzx`                                                           extends MediaType {\n    val value = \"application/lzx\"\n  }\n  type `Application/lzx` = `application/lzx`.type                                                           \n  case object `application/mspowerpoint`                                                  extends MediaType {\n    val value = \"application/mspowerpoint\"\n  }\n  type `Application/mspowerpoint` = `application/mspowerpoint`.type                                                  \n  case object `application/msword`                                                        extends MediaType {\n    val value = \"application/msword\"\n  }\n  type `Application/msword` = `application/msword`.type                                                        \n  case object `application/octet-stream`                                                  extends MediaType {\n    val value = \"application/octet-stream\"\n  }\n  type `Application/octet-stream` = `application/octet-stream`.type                                                  \n  case object `application/pdf`                                                           extends MediaType {\n    val value = \"application/pdf\"\n  }\n  type `Application/pdf` = `application/pdf`.type                                                           \n  case object `application/postscript`                                                    extends MediaType {\n    val value = \"application/postscript\"\n  }\n  type `Application/postscript` = `application/postscript`.type                                                    \n  case object `application/rss+xml`                                                       extends MediaType {\n    val value = \"application/rss+xml\"\n  }\n  type `Application/rss+xml` = `application/rss+xml`.type                                                       \n  case object `application/soap+xml`                                                      extends MediaType {\n    val value = \"application/soap+xml\"\n  }\n  type `Application/soap+xml` = `application/soap+xml`.type                                                      \n  case object `application/vnd.api+json`                                                  extends MediaType {\n    val value = \"application/vnd.api+json\"\n  }\n  type `Application/vnd.api+json` = `application/vnd.api+json`.type                                                  \n  case object `application/vnd.google-earth.kml+xml`                                      extends MediaType {\n    val value = \"application/vnd.google-earth.kml+xml\"\n  }\n  type `Application/vnd.google-earth.kml+xml` = `application/vnd.google-earth.kml+xml`.type                                      \n  case object `application/vnd.google-earth.kmz`                                          extends MediaType {\n    val value = \"application/vnd.google-earth.kmz\"\n  }\n  type `Application/vnd.google-earth.kmz` = `application/vnd.google-earth.kmz`.type                                          \n  case object `application/vnd.ms-fontobject`                                             extends MediaType {\n    val value = \"application/vnd.ms-fontobject\"\n  }\n  type `Application/vnd.ms-fontobject` = `application/vnd.ms-fontobject`.type                                             \n  case object `application/vnd.oasis.opendocument.chart`                                  extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.chart\"\n  }\n  type `Application/vnd.oasis.opendocument.chart` = `application/vnd.oasis.opendocument.chart`.type                                  \n  case object `application/vnd.oasis.opendocument.database`                               extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.database\"\n  }\n  type `Application/vnd.oasis.opendocument.database` = `application/vnd.oasis.opendocument.database`.type                               \n  case object `application/vnd.oasis.opendocument.formula`                                extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.formula\"\n  }\n  type `Application/vnd.oasis.opendocument.formula` = `application/vnd.oasis.opendocument.formula`.type                                \n  case object `application/vnd.oasis.opendocument.graphics`                               extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.graphics\"\n  }\n  type `Application/vnd.oasis.opendocument.graphics` = `application/vnd.oasis.opendocument.graphics`.type                               \n  case object `application/vnd.oasis.opendocument.image`                                  extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.image\"\n  }\n  type `Application/vnd.oasis.opendocument.image` = `application/vnd.oasis.opendocument.image`.type                                  \n  case object `application/vnd.oasis.opendocument.presentation`                           extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.presentation\"\n  }\n  type `Application/vnd.oasis.opendocument.presentation` = `application/vnd.oasis.opendocument.presentation`.type                           \n  case object `application/vnd.oasis.opendocument.spreadsheet`                            extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.spreadsheet\"\n  }\n  type `Application/vnd.oasis.opendocument.spreadsheet` = `application/vnd.oasis.opendocument.spreadsheet`.type                            \n  case object `application/vnd.oasis.opendocument.text`                                   extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.text\"\n  }\n  type `Application/vnd.oasis.opendocument.text` = `application/vnd.oasis.opendocument.text`.type                                   \n  case object `application/vnd.oasis.opendocument.text-master`                            extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.text-master\"\n  }\n  type `Application/vnd.oasis.opendocument.text-master` = `application/vnd.oasis.opendocument.text-master`.type                            \n  case object `application/vnd.oasis.opendocument.text-web`                               extends MediaType {\n    val value = \"application/vnd.oasis.opendocument.text-web\"\n  }\n  type `Application/vnd.oasis.opendocument.text-web` = `application/vnd.oasis.opendocument.text-web`.type                               \n  case object `application/vnd.openxmlformats-officedocument.presentationml.presentation` extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.presentationml.presentation\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.presentationml.presentation` = `application/vnd.openxmlformats-officedocument.presentationml.presentation`.type \n  case object `application/vnd.openxmlformats-officedocument.presentationml.slide`        extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.presentationml.slide\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.presentationml.slide` = `application/vnd.openxmlformats-officedocument.presentationml.slide`.type        \n  case object `application/vnd.openxmlformats-officedocument.presentationml.slideshow`    extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.presentationml.slideshow\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.presentationml.slideshow` = `application/vnd.openxmlformats-officedocument.presentationml.slideshow`.type    \n  case object `application/vnd.openxmlformats-officedocument.presentationml.template`     extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.presentationml.template\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.presentationml.template` = `application/vnd.openxmlformats-officedocument.presentationml.template`.type     \n  case object `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`         extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` = `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`.type         \n  case object `application/vnd.openxmlformats-officedocument.spreadsheetml.template`      extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.spreadsheetml.template\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.spreadsheetml.template` = `application/vnd.openxmlformats-officedocument.spreadsheetml.template`.type      \n  case object `application/vnd.openxmlformats-officedocument.wordprocessingml.document`   extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.wordprocessingml.document` = `application/vnd.openxmlformats-officedocument.wordprocessingml.document`.type   \n  case object `application/vnd.openxmlformats-officedocument.wordprocessingml.template`   extends MediaType {\n    val value = \"application/vnd.openxmlformats-officedocument.wordprocessingml.template\"\n  }\n  type `Application/vnd.openxmlformats-officedocument.wordprocessingml.template` = `application/vnd.openxmlformats-officedocument.wordprocessingml.template`.type   \n  case object `application/x-7z-compressed`                                               extends MediaType {\n    val value = \"application/x-7z-compressed\"\n  }\n  type `Application/x-7z-compressed` = `application/x-7z-compressed`.type                                               \n  case object `application/x-ace-compressed`                                              extends MediaType {\n    val value = \"application/x-ace-compressed\"\n  }\n  type `Application/x-ace-compressed` = `application/x-ace-compressed`.type                                              \n  case object `application/x-apple-diskimage`                                             extends MediaType {\n    val value = \"application/x-apple-diskimage\"\n  }\n  type `Application/x-apple-diskimage` = `application/x-apple-diskimage`.type                                             \n  case object `application/x-arc-compressed`                                              extends MediaType {\n    val value = \"application/x-arc-compressed\"\n  }\n  type `Application/x-arc-compressed` = `application/x-arc-compressed`.type                                              \n  case object `application/x-bzip`                                                        extends MediaType {\n    val value = \"application/x-bzip\"\n  }\n  type `Application/x-bzip` = `application/x-bzip`.type                                                        \n  case object `application/x-bzip2`                                                       extends MediaType {\n    val value = \"application/x-bzip2\"\n  }\n  type `Application/x-bzip2` = `application/x-bzip2`.type                                                       \n  case object `application/x-chrome-extension`                                            extends MediaType {\n    val value = \"application/x-chrome-extension\"\n  }\n  type `Application/x-chrome-extension` = `application/x-chrome-extension`.type                                            \n  case object `application/x-compress`                                                    extends MediaType {\n    val value = \"application/x-compress\"\n  }\n  type `Application/x-compress` = `application/x-compress`.type                                                    \n  case object `application/x-compressed`                                                  extends MediaType {\n    val value = \"application/x-compressed\"\n  }\n  type `Application/x-compressed` = `application/x-compressed`.type                                                  \n  case object `application/x-debian-package`                                              extends MediaType {\n    val value = \"application/x-debian-package\"\n  }\n  type `Application/x-debian-package` = `application/x-debian-package`.type                                              \n  case object `application/x-dvi`                                                         extends MediaType {\n    val value = \"application/x-dvi\"\n  }\n  type `Application/x-dvi` = `application/x-dvi`.type                                                         \n  case object `application/x-font-truetype`                                               extends MediaType {\n    val value = \"application/x-font-truetype\"\n  }\n  type `Application/x-font-truetype` = `application/x-font-truetype`.type                                               \n  case object `application/x-font-opentype`                                               extends MediaType {\n    val value = \"application/x-font-opentype\"\n  }\n  type `Application/x-font-opentype` = `application/x-font-opentype`.type                                               \n  case object `application/x-gtar`                                                        extends MediaType {\n    val value = \"application/x-gtar\"\n  }\n  type `Application/x-gtar` = `application/x-gtar`.type                                                        \n  case object `application/x-gzip`                                                        extends MediaType {\n    val value = \"application/x-gzip\"\n  }\n  type `Application/x-gzip` = `application/x-gzip`.type                                                        \n  case object `application/x-latex`                                                       extends MediaType {\n    val value = \"application/x-latex\"\n  }\n  type `Application/x-latex` = `application/x-latex`.type                                                       \n  case object `application/x-rar-compressed`                                              extends MediaType {\n    val value = \"application/x-rar-compressed\"\n  }\n  type `Application/x-rar-compressed` = `application/x-rar-compressed`.type                                              \n  case object `application/x-redhat-package-manager`                                      extends MediaType {\n    val value = \"application/x-redhat-package-manager\"\n  }\n  type `Application/x-redhat-package-manager` = `application/x-redhat-package-manager`.type                                      \n  case object `application/x-shockwave-flash`                                             extends MediaType {\n    val value = \"application/x-shockwave-flash\"\n  }\n  type `Application/x-shockwave-flash` = `application/x-shockwave-flash`.type                                             \n  case object `application/x-tar`                                                         extends MediaType {\n    val value = \"application/x-tar\"\n  }\n  type `Application/x-tar` = `application/x-tar`.type                                                         \n  case object `application/x-tex`                                                         extends MediaType {\n    val value = \"application/x-tex\"\n  }\n  type `Application/x-tex` = `application/x-tex`.type                                                         \n  case object `application/x-texinfo`                                                     extends MediaType {\n    val value = \"application/x-texinfo\"\n  }\n  type `Application/x-texinfo` = `application/x-texinfo`.type                                                     \n  case object `application/x-vrml`                                                        extends MediaType {\n    val value = \"application/x-vrml\"\n  }\n  type `Application/x-vrml` = `application/x-vrml`.type                                                        \n  case object `application/x-www-form-urlencoded`                                         extends MediaType {\n    val value = \"application/x-www-form-urlencoded\"\n  }\n  type `Application/x-www-form-urlencoded` = `application/x-www-form-urlencoded`.type                                         \n  case object `application/x-x509-ca-cert`                                                extends MediaType {\n    val value = \"application/x-x509-ca-cert\"\n  }\n  type `Application/x-x509-ca-cert` = `application/x-x509-ca-cert`.type                                                \n  case object `application/x-xpinstall`                                                   extends MediaType {\n    val value = \"application/x-xpinstall\"\n  }\n  type `Application/x-xpinstall` = `application/x-xpinstall`.type                                                   \n  case object `application/xhtml+xml`                                                     extends MediaType {\n    val value = \"application/xhtml+xml\"\n  }\n  type `Application/xhtml+xml` = `application/xhtml+xml`.type                                                     \n  case object `application/xml-dtd`                                                       extends MediaType {\n    val value = \"application/xml-dtd\"\n  }\n  type `Application/xml-dtd` = `application/xml-dtd`.type                                                       \n  case object `application/xml`                                                           extends MediaType {\n    val value = \"application/xml\"\n  }\n  type `Application/xml` = `application/xml`.type                                                           \n  case object `application/zip`                                                           extends MediaType {\n    val value = \"application/zip\"\n  }\n  type `Application/zip` = `application/zip`.type                                                           \n\n  case object `audio/aiff`        extends MediaType {\n    val value = \"audio/aiff\"\n  }\n  type `Audio/aiff` = `audio/aiff`.type\n  case object `audio/basic`       extends MediaType {\n    val value = \"audio/basic\"\n  }\n  type `Audio/basic` = `audio/basic`.type       \n  case object `audio/midi`        extends MediaType {\n    val value = \"audio/midi\"\n  }\n  type `Audio/midi` = `audio/midi`.type        \n  case object `audio/mod`         extends MediaType {\n    val value = \"audio/mod\"\n  }\n  type `Audio/mod` = `audio/mod`.type         \n  case object `audio/mpeg`        extends MediaType {\n    val value = \"audio/mpeg\"\n  }\n  type `Audio/mpeg` = `audio/mpeg`.type        \n  case object `audio/ogg`         extends MediaType {\n    val value = \"audio/ogg\"\n  }\n  type `Audio/ogg` = `audio/ogg`.type         \n  case object `audio/voc`         extends MediaType {\n    val value = \"audio/voc\"\n  }\n  type `Audio/voc` = `audio/voc`.type\n  case object `audio/vorbis`      extends MediaType {\n    val value = \"audio/vorbis\"\n  }\n  type `Audio/vorbis` = `audio/vorbis`.type\n  case object `audio/voxware`     extends MediaType {\n    val value = \"audio/voxware\"\n  }\n  type `Audio/voxware` = `audio/voxware`.type     \n  case object `audio/wav`         extends MediaType {\n    val value = \"audio/wav\"\n  }\n  type `Audio/wav` = `audio/wav`.type\n  case object `audio/x-realaudio` extends MediaType {\n    val value = \"audio/x-reala\"\n  }\n  type `Audio/x-realaudio` = `audio/x-realaudio`.type \n  case object `audio/x-psid`      extends MediaType {\n    val value = \"audio/x-psid\"\n  }\n  type `Audio/x-psid` = `audio/x-psid`.type      \n  case object `audio/xm`          extends MediaType {\n    val value = \"audio/xm\"\n  }\n  type `Audio/xm` = `audio/xm`.type          \n  case object `audio/webm`        extends MediaType {\n    val value = \"audio/webm\"\n  }\n  type `Audio/webm` = `audio/webm`.type        \n\n  case object `image/gif`         extends MediaType {\n    val value = \"image/gif\"\n  }\n  type `Image/gif` = `image/gif`.type\n  case object `image/jpeg`        extends MediaType {\n    val value = \"image/jpeg\"\n  }\n  type `Image/jpeg` = `image/jpeg`.type        \n  case object `image/pict`        extends MediaType {\n    val value = \"image/pict\"\n  }\n  type `Image/pict` = `image/pict`.type        \n  case object `image/png`         extends MediaType {\n    val value = \"image/png\"\n  }\n  type `Image/png` = `image/png`.type         \n  case object `image/svg+xml`     extends MediaType {\n    val value = \"image/svg+xml\"\n  }\n  type `Image/svg+xml` = `image/svg+xml`.type     \n  case object `image/svgz`        extends MediaType {\n    val value = \"image/svgz\"\n  }\n  type `Image/svgz` = `image/svgz`.type        \n  case object `image/tiff`        extends MediaType {\n    val value = \"image/tiff\"\n  }\n  type `Image/tiff` = `image/tiff`.type        \n  case object `image/x-icon`       extends MediaType {\n    val value = \"image/x-icon\"\n  }\n  type `Image/x-icon` = `image/x-icon`.type\n  case object `image/x-ms-bmp`    extends MediaType {\n    val value = \"image/x-ms-bmp\"\n  }\n  type `Image/x-ms-bmp` = `image/x-ms-bmp`.type    \n  case object `image/x-pcx`       extends MediaType {\n    val value = \"image/x-pcx\"\n  }\n  type `Image/x-pcx` = `image/x-pcx`.type\n  case object `image/x-pict`      extends MediaType {\n    val value = \"image/x-pict\"\n  }\n  type `Image/x-pict` = `image/x-pict`.type      \n  case object `image/x-quicktime` extends MediaType {\n    val value = \"image/x-quicktime\"\n  }\n  type `Image/x-quicktime` = `image/x-quicktime`.type \n  case object `image/x-rgb`       extends MediaType {\n    val value = \"image/x-rgb\"\n  }\n  type `Image/x-rgb` = `image/x-rgb`.type       \n  case object `image/x-xbitmap`   extends MediaType {\n    val value = \"image/x-xbitmap\"\n  }\n  type `Image/x-xbitmap` = `image/x-xbitmap`.type   \n  case object `image/x-xpixmap`   extends MediaType {\n    val value = \"image/x-xpixmap\"\n  }\n  type `Image/x-xpixmap` = `image/x-xpixmap`.type   \n  case object `image/webp`        extends MediaType {\n    val value = \"image/webp\"\n  }\n  type `Image/webp` = `image/webp`.type        \n\n  case object `message/http`            extends MediaType {\n    val value = \"message/http\"\n  }\n  type `Message/http` = `message/http`.type\n  case object `message/delivery-status` extends MediaType {\n    val value = \"message/delivery-status\"\n  }\n  type `Message/delivery-status` = `message/delivery-status`.type \n  case object `message/rfc822`          extends MediaType {\n    val value = \"message/rfc822\"\n  }\n  type `Message/rfc822` = `message/rfc822`.type          \n\n  case object `text/asp`                  extends MediaType {\n    val value = \"text/asp\"\n  }\n  type `Text/asp` = `text/asp`.type                 \n  case object `text/cache-manifest`       extends MediaType {\n    val value = \"text/cache-manifest\"\n  }\n  type `Text/cache-manifest` = `text/cache-manifest`.type       \n  case object `text/calendar`             extends MediaType {\n    val value = \"text/calendar\"\n  }\n  type `Text/calendar` = `text/calendar`.type             \n  case object `text/css`                  extends MediaType {\n    val value = \"text/css\"\n  }\n  type `Text/css` = `text/css`.type                  \n  case object `text/csv`                  extends MediaType {\n    val value = \"text/css\"\n  }\n  type `Text/csv` = `text/csv`.type                  \n  case object `text/event-stream`         extends MediaType {\n    val value = \"text/event-stream\"\n  }\n  type `Text/event-stream` = `text/event-stream`.type         \n  case object `text/html`                 extends MediaType {\n    val value = \"text/html\"\n  }\n  type `Text/html` = `text/html`.type                 \n  case object `text/markdown`             extends MediaType {\n    val value = \"text/markdown\"\n  }\n  type `Text/markdown` = `text/markdown`.type             \n  case object `text/mcf`                  extends MediaType {\n    val value = \"text/mcf\"\n  }\n  type `Text/mcf` = `text/mcf`.type                  \n  case object `text/plain`                extends MediaType {\n    val value = \"text/plain\"\n  }\n  type `Text/plain` = `text/plain`.type                \n  case object `text/richtext`             extends MediaType {\n    val value = \"text/richtext\"\n  }\n  type `Text/richtext` = `text/richtext`.type             \n  case object `text/tab-separated-values` extends MediaType {\n    val value = \"text/tab-separated-values\"\n  }\n  type `Text/tab-separated-values` = `text/tab-separated-values`.type \n  case object `text/uri-list`             extends MediaType {\n    val value = \"text/uri-list\"\n  }\n  type `Text/uri-list` = `text/uri-list`.type\n  case object `text/vnd.wap.wml`          extends MediaType {\n    val value = \"text/vnd.wap.wml\"\n  }\n  type `Text/vnd.wap.wml` = `text/vnd.wap.wml`.type          \n  case object `text/vnd.wap.wmlscript`    extends MediaType {\n    val value = \"text/vnd.wap.wmlscript\"\n  }\n  type `Text/vnd.wap.wmlscript` = `text/vnd.wap.wmlscript`.type    \n  case object `text/x-asm`                extends MediaType {\n    val value = \"text/x-asm\"\n  }\n  type `Text/x-asm` = `text/x-asm`.type                \n  case object `text/x-c`                  extends MediaType {\n    val value = \"text/x-c\"\n  }\n  type `Text/x-c` = `text/x-c`.type                  \n  case object `text/x-component`          extends MediaType {\n    val value = \"text/x-component\"\n  }\n  type `Text/x-component` = `text/x-component`.type          \n  case object `text/x-h`                  extends MediaType {\n    val value = \"text/x-h\"\n  }\n  type `Text/x-h` = `text/x-h`.type                  \n  case object `text/x-java-source`        extends MediaType {\n    val value = \"text/x-java-source\"\n  }\n  type `Text/x-java-source` = `text/x-java-source`.type        \n  case object `text/x-pascal`             extends MediaType {\n    val value = \"text/x-pascal\"\n  }\n  type `Text/x-pascal` = `text/x-pascal`.type             \n  case object `text/x-script`             extends MediaType {\n    val value = \"text/x-script\"\n  }\n  type `Text/x-script` = `text/x-script`.type             \n  case object `text/x-scriptcsh`          extends MediaType {\n    val value = \"text/x-scriptcsh\"\n  }\n  type `Text/x-scriptcsh` = `text/x-scriptcsh`.type          \n  case object `text/x-scriptelisp`        extends MediaType {\n    val value = \"text/x-scriptelisp\"\n  }\n  type `Text/x-scriptelisp` = `text/x-scriptelisp`.type        \n  case object `text/x-scriptksh`          extends MediaType {\n    val value = \"text/x-scriptksh\"\n  }\n  type `Text/x-scriptksh` = `text/x-scriptksh`.type          \n  case object `text/x-scriptlisp`         extends MediaType {\n    val value = \"text/x-scriptlisp\"\n  }\n  type `Text/x-scriptlisp` = `text/x-scriptlisp`.type         \n  case object `text/x-scriptperl`         extends MediaType {\n    val value = \"text/x-scriptperl\"\n  }\n  type `Text/x-scriptperl` = `text/x-scriptperl`.type         \n  case object `text/x-scriptperl-module`  extends MediaType {\n    val value = \"text/x-scriptperl-module\"\n  }\n  type `Text/x-scriptperl-module` = `text/x-scriptperl-module`.type\n  case object `text/x-scriptphyton`       extends MediaType {\n    val value = \"text/x-scriptphyton\"\n  }\n  type `Text/x-scriptphyton` = `text/x-scriptphyton`.type       \n  case object `text/x-scriptrexx`         extends MediaType {\n    val value = \"text/x-scriptrexx\"\n  }\n  type `Text/x-scriptrexx` = `text/x-scriptrexx`.type         \n  case object `text/x-scriptscheme`       extends MediaType {\n    val value = \"text/x-scriptscheme\"\n  }\n  type `Text/x-scriptscheme` = `text/x-scriptscheme`.type       \n  case object `text/x-scriptsh`           extends MediaType {\n    val value = \"text/x-scriptsh\"\n  }\n  type `Text/x-scriptsh` = `text/x-scriptsh`.type           \n  case object `text/x-scripttcl`          extends MediaType {\n    val value = \"text/x-scripttcl\"\n  }\n  type `Text/x-scripttcl` = `text/x-scripttcl`.type          \n  case object `text/x-scripttcsh`         extends MediaType {\n    val value = \"text/x-scripttcsh\"\n  }\n  type `Text/x-scripttcsh` = `text/x-scripttcsh`.type         \n  case object `text/x-scriptzsh`          extends MediaType {\n    val value = \"text/x-scriptzsh\"\n  }\n  type `Text/x-scriptzsh` = `text/x-scriptzsh`.type          \n  case object `text/x-server-parsed-html` extends MediaType {\n    val value = \"text/x-server-parsed-html\"\n  }\n  type `Text/x-server-parsed-html` = `text/x-server-parsed-html`.type \n  case object `text/x-setext`             extends MediaType {\n    val value = \"text/x-setext\"\n  }\n  type `Text/x-setext` = `text/x-setext`.type             \n  case object `text/x-sgml`               extends MediaType {\n    val value = \"text/x-sgml\"\n  }\n  type `Text/x-sgml` = `text/x-sgml`.type               \n  case object `text/x-speech`             extends MediaType {\n    val value = \"text/x-speech\"\n  }\n  type `Text/x-speech` = `text/x-speech`.type             \n  case object `text/x-uuencode`           extends MediaType {\n    val value = \"text/x-uuencode\"\n  }\n  type `Text/x-uuencode` = `text/x-uuencode`.type           \n  case object `text/x-vcalendar`          extends MediaType {\n    val value = \"text/x-vcalendar\"\n  }\n  type `Text/x-vcalendar` = `text/x-vcalendar`.type          \n  case object `text/x-vcard`              extends MediaType {\n    val value = \"text/x-vcard\"\n  }\n  type `Text/x-vcard` = `text/x-vcard`.type              \n  case object `text/xml`                  extends MediaType {\n    val value = \"text/xml\"\n  }\n  type `Text/xml` = `text/xml`.type\n\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/TypeCarrier.scala",
    "content": "package typedapi.shared\n\nimport shapeless._\n\nimport scala.language.higherKinds\n\n/** As the name says this case class is only there it pass types around on the value level. */\nfinal case class TypeCarrier[A]()\n\n/** Derive a [[TypeCarrier]] from a type parameter and a singleton type. */\nfinal class PairTypeFromWitnessKey[F[_, _], V] {\n\n  def apply[K](wit: Witness.Lt[K]): TypeCarrier[F[K, V]] = TypeCarrier()\n}\n\n/** Derive a [[TypeCarrier]] from two singleton types. */\nfinal class PairTypeFromWitnesses[F[_, _]] {\n\n  def apply[K, V](kWit: Witness.Lt[K], vWit: Witness.Lt[V]): TypeCarrier[F[K, V]] = TypeCarrier()\n}\n\n/** Specific [[TypeCarrier]] for complete API types. */\nfinal case class ApiTypeCarrier[H <: HList]() {\n\n  def :|:[H1 <: HList](next: ApiTypeCarrier[H1]): CompositionCons[H1 :: H :: HNil] = CompositionCons()\n}\n\n/** Specific [[TypeCarrier]] for multiple API types. */\nfinal case class CompositionCons[H <: HList]() {\n\n  def :|:[H1 <: HList](next: ApiTypeCarrier[H1]): CompositionCons[H1 :: H] = CompositionCons()\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/TypeLevelFoldLeft.scala",
    "content": "package typedapi.shared\n\nimport shapeless._\n\nimport scala.annotation.implicitNotFound\n\n// INTERNAL API\n\n/** Reimplements shapeles Case2 but on the type level (no real HList instance). */\n@implicitNotFound(\"\"\"Woops, you shouldn't be here. We cannot find TypeLevelFoldFunction instance.\n\ninput: ${In}\naggregation: ${Agg}\"\"\")\nsealed trait TypeLevelFoldFunction[In, Agg] {\n\n  type Out\n}\n\nobject TypeLevelFoldFunction {\n\n  type Aux[In, Agg, Out0] = TypeLevelFoldFunction[In, Agg] { type Out = Out0 }\n\n  def at[In, Agg, Out0]: Aux[In, Agg, Out0] = new TypeLevelFoldFunction[In, Agg] {\n    type Out = Out0\n  }\n}\n\n/** Reimplements shapeless LeftFolder but on the type level (no real HList instance) */\n@implicitNotFound(\"\"\"Woops, you shouldn't be here. We cannot find TypeLevelFold instance.\n\nlist: ${H}\naggregation: ${Agg}\"\"\")\nsealed trait TypeLevelFoldLeft[H <: HList, Agg] extends Serializable {\n\n  type Out\n}\n\nobject TypeLevelFoldLeft {\n\n  type Aux[H <: HList, Agg, Out0] = TypeLevelFoldLeft[H, Agg] {\n    type Out = Out0\n  }\n}\n\ntrait TypeLevelFoldLeftLowPrio {\n\n  implicit def hnilCase[Agg]: TypeLevelFoldLeft.Aux[HNil, Agg, Agg] = new TypeLevelFoldLeft[HNil, Agg] {\n    type Out = Agg\n  }\n\n  implicit def foldCase[H, T <: HList, Agg, FtOut, FOut](implicit f: TypeLevelFoldFunction.Aux[H, Agg, FtOut], \n                                                                  next: Lazy[TypeLevelFoldLeft.Aux[T, FtOut, FOut]]): TypeLevelFoldLeft.Aux[H :: T, Agg, FOut] = new TypeLevelFoldLeft[H :: T, Agg] {\n    type Out = next.value.Out\n  }\n}\n\n/** Helper to work on a composition of HLists we want to fold over. */\n@implicitNotFound(\"\"\"Woops, you shouldn't be here. We cannot find TypeLevelFoldList instance.\n\napis: ${H}\"\"\")\ntrait TypeLevelFoldLeftList[H <: HList] {\n\n  type Out <: HList\n}\n\nobject TypeLevelFoldLeftList {\n\n  type Aux[H <: HList, Out0 <: HList] = TypeLevelFoldLeftList[H] {\n    type Out = Out0\n  }\n}\n\ntrait TypeLevelFoldLeftListLowPrio {\n\n  implicit def lastFoldLeftList[H <: HList, Agg](implicit folder0: TypeLevelFoldLeft[H, Agg]) = new TypeLevelFoldLeftList[H :: HNil] {\n    type Out = folder0.Out :: HNil\n  }\n\n  implicit def folderLeftList[H <: HList, Agg, T <: HList](implicit folder0: TypeLevelFoldLeft[H, Agg], list: TypeLevelFoldLeftList[T]) = new TypeLevelFoldLeftList[H :: T] {\n    type Out = folder0.Out :: list.Out\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/WitnessToString.scala",
    "content": "package typedapi.shared\n\nimport scala.annotation.implicitNotFound\n\n@implicitNotFound(\"Couldn't find transformation for witness ${K} to String.\")\nsealed trait WitnessToString[K] {\n\n  def show(key: K): String\n}\n\ntrait WitnessToStringLowPrio {\n\n  implicit def symbolKey[K <: Symbol] = new WitnessToString[K] {\n    def show(key: K): String = key.name\n  }\n\n  implicit def stringKey[K <: String] = new WitnessToString[K] {\n    def show(key: K): String = key\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/shared/package.scala",
    "content": "package typedapi\n\nimport shapeless.Witness\n\npackage object shared {\n\n  final val BodyField       = Witness('body)\n  final val RawHeadersField = Witness('rawHeaders)\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/util/Decoder.scala",
    "content": "package typedapi.util\n\nimport scala.language.higherKinds\n\ntrait Decoder[F[_], A] extends (String => F[Either[Exception, A]])\n\nobject Decoder {\n\n  def apply[F[_], A](decoder: String => F[Either[Exception, A]]): Decoder[F, A] = new Decoder[F, A] {\n    def apply(raw: String): F[Either[Exception, A]] = decoder(raw)\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/typedapi/util/Encoder.scala",
    "content": "package typedapi.util\n\nimport scala.language.higherKinds\n\ntrait Encoder[F[_], A] extends (A => F[String])\n\nobject Encoder {\n\n  def apply[F[_], A](encoder: A => F[String]): Encoder[F, A] = new Encoder[F, A] {\n    def apply(a: A): F[String] = encoder(a)\n  }\n}\n"
  },
  {
    "path": "shared/src/test/scala/typedapi/ApiDefinitionSpec.scala",
    "content": "package typedapi\n\nimport typedapi.shared._\nimport shapeless._\n\nimport SpecUtil._\n\n// compilation-only test\nobject ApiDefinitionSpec {\n\n  import MediaTypes._\n\n  case class Foo()\n\n  val testW  = Witness(\"test\")\n  val test2W = Witness(\"test2\")\n  val fooW   = Witness('foo)\n  val barW   = Witness('bah)\n\n  type Base = PathElement[testW.T] :: HNil\n\n  // path lists\n  testCompile(Root)[HNil]\n  testCompile(Root / \"test\")[PathElement[testW.T] :: HNil]\n  testCompile(Root / \"test\" / \"test2\")[PathElement[test2W.T] :: PathElement[testW.T] :: HNil]\n  testCompile(Root / \"test\" / Segment[Int]('foo))[SegmentParam[fooW.T, Int] :: PathElement[testW.T] :: HNil]\n  testCompile(Root / Segment[Int]('foo) / \"test\")[PathElement[testW.T] :: SegmentParam[fooW.T, Int] :: HNil]\n\n  // query lists\n  testCompile(Queries)[HNil]\n  testCompile(Queries add[Int](fooW))[QueryParam[fooW.T, Int] :: HNil]\n  testCompile(Queries add[Int](fooW) add[Int](barW))[QueryParam[barW.T, Int] :: QueryParam[fooW.T, Int] :: HNil]\n\n  // header lists\n  testCompile(Headers)[HNil]\n  testCompile(Headers add[Int](fooW))[HeaderParam[fooW.T, Int] :: HNil]\n  testCompile(Headers add[Int](fooW) add[Int](barW))[HeaderParam[barW.T, Int] :: HeaderParam[fooW.T, Int] :: HNil]\n  testCompile(Headers add(fooW, testW))[FixedHeaderElement[fooW.T, testW.T] :: HNil]\n  testCompile(Headers client(fooW, testW))[ClientHeaderElement[fooW.T, testW.T] :: HNil]\n  testCompile(Headers client[String](fooW))[ClientHeaderParam[fooW.T, String] :: HNil]\n  testCompile(Headers.clientColl[String])[ClientHeaderCollParam[String] :: HNil]\n  testCompile(Headers serverSend(fooW, testW))[ServerHeaderSendElement[fooW.T, testW.T] :: HNil]\n  testCompile(Headers serverMatch[String](fooW))[ServerHeaderMatchParam[fooW.T, String] :: HNil]\n  testCompile(Headers serverMatch[String](fooW))[ServerHeaderMatchParam[fooW.T, String] :: HNil]\n\n  // methods\n  testCompile(api(Get[Json, Foo]))[GetElement[`Application/json`, Foo] :: HNil]\n  test.illTyped(\"apiWothBody(Get[Foo], ReqBody[Foo])\")\n  testCompile(api(Put[Json, Foo]))[PutElement[`Application/json`, Foo] :: HNil]\n  testCompile(apiWithBody(Put[Json, Foo], ReqBody[Plain, Foo]))[PutWithBodyElement[`Text/plain`, Foo, `Application/json`, Foo] :: HNil]\n  testCompile(api(Post[Json, Foo]))[PostElement[`Application/json`, Foo] :: HNil]\n  testCompile(apiWithBody(Post[Json, Foo], ReqBody[Plain, Foo]))[PostWithBodyElement[`Text/plain`, Foo, `Application/json`, Foo] :: HNil]\n  testCompile(api(Delete[Json, Foo]))[DeleteElement[`Application/json`, Foo] :: HNil]\n  test.illTyped(\"apiWothBody(Delete[Json, Foo], ReqBody[Plain, Foo])\")\n\n  // whole api\n  testCompile(\n    api(Get[Json, Foo], Root / \"test\" / Segment[Int]('foo), Queries add[String]('foo), Headers add[Double]('foo))\n  )[GetElement[`Application/json`, Foo] :: HeaderParam[fooW.T, Double] :: QueryParam[fooW.T, String] :: SegmentParam[fooW.T, Int] :: PathElement[testW.T] :: HNil]\n}\n"
  },
  {
    "path": "shared/src/test/scala/typedapi/SpecUtil.scala",
    "content": "package typedapi\n\nimport shapeless.HList\n\nimport scala.language.higherKinds\n\nobject SpecUtil {\n\n  class TestHelper[Act <: HList] {\n\n    def apply[Exp <: HList](implicit ev: Act =:= Exp) = Unit\n  }\n\n  def testCompile[F[_ <: HList], Act <: HList](cons: F[Act]) = new TestHelper[Act]\n}\n"
  },
  {
    "path": "shared/src/test/scala/typedapi/dsl/ApiDslSpec.scala",
    "content": "package typedapi.dsl\n\nimport typedapi.SpecUtil._\nimport typedapi.shared._\nimport shapeless._\n\n// compilation-only test\nobject ApiDslSpec {\n\n  import MediaTypes._\n\n  case class Foo()\n\n  val testW = Witness(\"test\")\n  val fooW  = Witness('foo)\n  val base  = := :> \"test\"\n\n  type Base = PathElement[testW.T] :: HNil\n\n  val a = Query[Int].apply(fooW)\n\n  // empty path\n  testCompile(:= :> Segment[Int](fooW))[SegmentParam[fooW.T, Int] :: HNil]\n  testCompile(:= :> Query[Int](fooW))[QueryParam[fooW.T, Int] :: HNil]\n  testCompile(:= :> Header[Int](fooW))[HeaderParam[fooW.T, Int] :: HNil]\n  testCompile(:= :> Get[Json, Foo])[GetElement[`Application/json`, Foo] :: HNil]\n\n  // path: add every element\n  testCompile(base :> Segment[Int](fooW))[SegmentParam[fooW.T, Int] :: Base]\n  testCompile(base :> Query[Int](fooW))[QueryParam[fooW.T, Int] :: Base]\n  testCompile(base :> Header[Int](fooW))[HeaderParam[fooW.T, Int] :: Base]\n  testCompile(base :> Get[Json, Foo])[GetElement[`Application/json`, Foo] :: Base]\n\n  // segment: add every element\n  val _baseSeg = base :> Segment[Int](fooW)\n\n  type _BaseSeg = SegmentParam[fooW.T, Int] :: Base\n\n  testCompile(_baseSeg :> Segment[Int](fooW))[SegmentParam[fooW.T, Int] :: _BaseSeg]\n  testCompile(_baseSeg :> Query[Int](fooW))[QueryParam[fooW.T, Int] :: _BaseSeg]\n  testCompile(_baseSeg :> Header[Int](fooW))[HeaderParam[fooW.T, Int] :: _BaseSeg]\n  testCompile(_baseSeg :> Get[Json, Foo])[GetElement[`Application/json`, Foo] :: _BaseSeg]\n  \n  // query: add queries, headers, body and final\n  val _baseQ = base :> Query[Int](fooW)\n\n  type _BaseQ = QueryParam[fooW.T, Int] :: Base\n\n  test.illTyped(\"_baseQ :> \\\"fail\\\"\")\n  test.illTyped(\"_baseQ :> Segment[Int](fooW)\")\n  testCompile(_baseQ :> Query[Int](fooW))[QueryParam[fooW.T, Int] :: _BaseQ]\n  testCompile(_baseQ :> Header[Int](fooW))[HeaderParam[fooW.T, Int] :: _BaseQ]\n  testCompile(_baseQ :> Get[Json, Foo])[GetElement[`Application/json`, Foo] :: _BaseQ]\n  \n  // header: add header, final\n  val _baseH = base :> Header[Int](fooW)\n\n  type _BaseH = HeaderParam[fooW.T, Int] :: Base\n\n  test.illTyped(\"_baseH :> \\\"fail\\\"\")\n  test.illTyped(\"_baseH :> Segment[Int](fooW)\")\n  test.illTyped(\"_baseH :> Query[Int](fooW)\")\n  testCompile(_baseH :> Header[Int](fooW))[HeaderParam[fooW.T, Int] :: _BaseH]\n  testCompile(_baseH :> Header(fooW, testW) :> Header[Int](fooW))[HeaderParam[fooW.T, Int] :: FixedHeaderElement[fooW.T, testW.T] :: _BaseH]\n  testCompile(_baseH :> Client.Header[String](fooW))[ClientHeaderParam[fooW.T, String] :: _BaseH]\n  testCompile(_baseH :> Client.Header(fooW, testW))[ClientHeaderElement[fooW.T, testW.T] :: _BaseH]\n  testCompile(_baseH :> Server.Send(fooW, testW))[ServerHeaderSendElement[fooW.T, testW.T] :: _BaseH]\n  testCompile(_baseH :> Server.Match[String](fooW))[ServerHeaderMatchParam[fooW.T, String] :: _BaseH]\n  testCompile(_baseH :> Get[Json, Foo])[GetElement[`Application/json`, Foo] :: _BaseH]\n\n  // request body: add put or post\n  val _baseRB = base :> ReqBody[Plain, Foo]\n\n  type _BaseRB = Base\n\n  test.illTyped(\"_baseRB :> Segment[Int](fooW)\")\n  test.illTyped(\"_baseRB :> Query[Int](fooW)\")\n  test.illTyped(\"_baseRB :> Header[Int](fooW)\")\n  test.illTyped(\"_baseRB :> Get[Json, Foo]\")\n  testCompile(_baseRB :> Put[Json, Foo])[PutWithBodyElement[`Text/plain`, Foo, `Application/json`, Foo] :: _BaseRB]\n  testCompile(_baseRB :> Post[Json, Foo])[PostWithBodyElement[`Text/plain`, Foo, `Application/json`, Foo] :: _BaseRB]\n\n  // method: nothing at all\n  val _baseF = base :> Get[Json, Foo]\n\n  test.illTyped(\"_baseF :> Segment[Int](fooW)\")\n  test.illTyped(\"_baseF :> Query[Int](fooW)\")\n  test.illTyped(\"_baseF :> Header[Int](fooW)\")\n  test.illTyped(\"_baseF :> Get[Json, Foo]\")\n}\n"
  },
  {
    "path": "shared/src/test/scala/typedapi/shared/ApiTransformerSpec.scala",
    "content": "package typedapi.shared\n\nimport typedapi.Json\nimport shapeless._\nimport shapeless.labelled.FieldType\n\n// compilation-only test\nfinal class ApiTransformerSpec extends TypeLevelFoldLeftLowPrio with ApiTransformer {\n\n  case class Foo()\n\n  def testCompile[H <: HList, Out](implicit folder: TypeLevelFoldLeft.Aux[H, Unit, Out]): TypeLevelFoldLeft.Aux[H, Unit, Out] = \n    folder\n\n  val pathW = Witness(\"test\")\n  val fooW  = Witness('foo)\n  val barW  = Witness('bar)\n\n  testCompile[GetElement[Json, Foo] :: HNil, (HNil, HNil, HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[PutElement[Json, Foo] :: HNil, (HNil, HNil, HNil, PutCall, FieldType[Json, Foo])]\n  testCompile[PutWithBodyElement[Json, Foo, Json, Foo] :: HNil, (HNil, FieldType[Json, BodyField.T] :: HNil, Foo :: HNil, PutWithBodyCall, FieldType[Json, Foo])]\n  testCompile[PostElement[Json, Foo] :: HNil, (HNil, HNil, HNil, PostCall, FieldType[Json, Foo])]\n  testCompile[PostWithBodyElement[Json, Foo, Json, Foo] :: HNil, (HNil, FieldType[Json, BodyField.T] :: HNil, Foo :: HNil, PostWithBodyCall, FieldType[Json, Foo])]\n  testCompile[DeleteElement[Json, Foo] :: HNil, (HNil, HNil, HNil, DeleteCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: PathElement[pathW.T] :: HNil, (pathW.T :: HNil, HNil, HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: SegmentParam[fooW.T, String] :: HNil, (SegmentInput :: HNil, fooW.T :: HNil, String :: HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: QueryParam[fooW.T, String] :: HNil, (QueryInput :: HNil, fooW.T :: HNil, String :: HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: QueryParam[fooW.T, List[String]] :: HNil, (QueryInput :: HNil, fooW.T :: HNil, List[String] :: HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: HeaderParam[fooW.T, String] :: HNil, (HeaderInput :: HNil, fooW.T :: HNil, String :: HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: FixedHeaderElement[fooW.T, barW.T] :: HNil, (FixedHeader[fooW.T, barW.T] :: HNil, HNil, HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: ClientHeaderParam[fooW.T, String] :: HNil, (ClientHeaderInput :: HNil, fooW.T :: HNil, String :: HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: ClientHeaderElement[fooW.T, barW.T] :: HNil, (ClientHeader[fooW.T, barW.T] :: HNil, HNil, HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: ClientHeaderCollParam[Int] :: HNil, (ClientHeaderCollInput :: HNil, HNil, Map[String, Int] :: HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: ServerHeaderMatchParam[fooW.T, String] :: HNil, (ServerHeaderMatchInput :: HNil, fooW.T :: HNil, Map[String, String] :: HNil, GetCall, FieldType[Json, Foo])]\n  testCompile[GetElement[Json, Foo] :: ServerHeaderSendElement[fooW.T, barW.T] :: HNil, (ServerHeaderSend[fooW.T, barW.T] :: HNil, HNil, HNil, GetCall, FieldType[Json, Foo])]\n\n  testCompile[\n    GetElement[Json, Foo] :: HeaderParam[fooW.T, Boolean] :: QueryParam[fooW.T, Int] :: SegmentParam[fooW.T, String] :: PathElement[pathW.T] :: HNil, \n    (pathW.T :: SegmentInput :: QueryInput :: HeaderInput :: HNil, fooW.T :: fooW.T :: fooW.T :: HNil, String :: Int :: Boolean :: HNil, GetCall, FieldType[Json, Foo])\n  ]\n}\n"
  }
]